Support for org.json.JSONObject as @XmlElement properties?

555 views
Skip to first unread message

Kean Erickson

unread,
Nov 9, 2017, 9:07:51 PM11/9/17
to jackson-user
Currently, any @XmlElement JSONObjects in an @XmlRootElement class iare sent out as a blank string. Being able to simply use a json object rather than package my existing json into a string (handling for curlies rather than a blank string as output, yada yada) would clean up my code rather nicely.

Maybe it's naiive to say, but all examples of implementing this marshaling myself (based on the two other threads here about this) looks like a bunch of unsightly cruft / plumbing that would stick out like a sore thumb in my codebase.  Is there any way that JSONObjects could be supported as output, or would something like that never even be considered for the roadmap? Thanks!

Tatu Saloranta

unread,
Nov 10, 2017, 4:21:26 PM11/10/17
to jackson-user
If you mean whether you could use module with Java classes like:

public class Stuff {
@JacksonAnnotation // placeholder for any annotation Jackson knows
public JSONObject extra;
}

yes, that is expected usage. Ont thing to note is that `@XmlElement`
is JAXB annotation, and you need another module
(`jackson-module-jaxb-annotations`)
to support that one (if you used `@JsonProperty` instead that would
work without additional modules as it is Jackson native)

If I misunderstood the question, could you add a sample of how you are
trying to use the module?

-+ Tatu +-

Kean Erickson

unread,
Nov 13, 2017, 2:12:54 PM11/13/17
to jackson-user
Hi Tatu, thanks for getting back to me. I do have the jaxb-annotations module, currently, as well as jackson-datatype-json-org and jackson-databind. Here's a stub of my application config:

    public class ApplicationConfig extends Application {
        private final Set<Class<?>> classes;

        public ApplicationConfig() {

            HashSet<Class<?>> c = new HashSet<>();
            c.add(JacksonJsonProvider.class);
            c.add(JacksonJaxbJsonProvider.class);
            c.add(ObjectMapperProvider.class);
            classes = Collections.unmodifiableSet(c);
           
            // ...
        }
       
       
        @Provider
        public static class ObjectMapperProvider implements ContextResolver<ObjectMapper> {

            private final ObjectMapper mapper;

            public ObjectMapperProvider() {
                mapper = new ObjectMapper();
                mapper.registerModule(new JsonOrgModule());
            }

            @Override
            public ObjectMapper getContext(Class<?> type) {
                return mapper;
            }
        }
    }


And then in my @XmlRootElement-annotated class, I have a member..

    @XmlElement private JSONObject obj;

This item always comes back as "" in any JSON response, rather than as a json object with populated contents. Using @JsonProperty on the JSONObject has the same result. JSONObject is what I use in the rest of the application, so I'm trying to avoid having to do any conversion with Jackson's JsonNode or similar.


Cheers

Tatu Saloranta

unread,
Nov 13, 2017, 4:33:37 PM11/13/17
to jackson-user
Ok. If so it might make sense to first make sure that framework is
using properly configured mapper.
One way would be to create a simple stand-alone test with POJO,
outside of framework (JAX-RS?).
If I understood situation correctly it should just work. One thing I
don't know is why value would be serialized
as empty String -- I don't see how Jackson would ever produce that.

Anyway: if stand-alone case fails as explained I'd like an issue filed
for the module since this use case
(reading JSON into org.json model; writing JSON out of org.json model)
is what module was written for.
So it should really "just work".

-+ Tatu +-
> --
> You received this message because you are subscribed to the Google Groups
> "jackson-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to jackson-user...@googlegroups.com.
> To post to this group, send email to jackso...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Kean Erickson

unread,
Nov 14, 2017, 9:22:45 PM11/14/17
to jackso...@googlegroups.com
Hey there Tatu,


So after adding a provider class extending JacksonJaxbJsonProvider, I've had success in producing JSONObjects over GET requests, but there's still some trouble still with interpreting POSTed json in requests as JSONObject. I was curious, should writing a custom MessageBodyReader still be necessary with JsonOrgModule in use?


/* Application logic.. */

JacksonConfigFeature jsonJacksonFeature = new JacksonConfigFeature();
singletons.add(jsonJacksonFeature);



/* Jackson feature class.. */

@Provider
public final class JacksonConfigFeature implements Feature {

    @Override
    public boolean configure(final FeatureContext context) {
        context.register(JacksonConfigProvider.class);
        return true;
    }
}


/* Config provider class.. */

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonConfigProvider extends JacksonJaxbJsonProvider  {

    private static ObjectMapper mapper = new ObjectMapper();
    static {
        mapper.registerModule(new JaxbAnnotationModule());
        mapper.registerModule(new JsonOrgModule());
     }

    public JacksonConfigProvider() {
        setMapper(mapper);
    }
}



/* Field in my DTO */
@XmlElement private JSONObject json;


I removed the implements ContextResolver<ObjectMapper> logic as it didn't seem to be making a difference--is it necessary? Having one seems to always result in JSONObject getting output as string--this was my original problem.


Cheers,
-Kean

Tatu Saloranta

unread,
Nov 15, 2017, 1:30:56 AM11/15/17
to jackson-user
On Tue, Nov 14, 2017 at 6:22 PM, Kean Erickson <kean.e...@gmail.com> wrote:
> Hey there Tatu,
>
>
> So after adding a provider class extending JacksonJaxbJsonProvider, I've had
> success in producing JSONObjects over GET requests, but there's still some
> trouble still with interpreting POSTed json in requests as JSONObject. I was
> curious, should writing a custom MessageBodyReader still be necessary with
> JsonOrgModule in use?

It should work just fine for GETs, POSTs and PUTs. Should not require
custom MessageBodyReader.
It has been a while since I had to last manually set things up so
unfortunately I don't know.
But I think any datatype module should have similar issues so when
searching for solutions
(StackOverflow is often a good resource), may want to see if there are
questions about
more popular modules like Joda, Guava or Java8 date/time modules.

Or more generally questions about injecting/initializing ObjectMapper to use.
One trick is to get access to `ObjectMapper` framework uses and
register module on that:
this actually works as mapper is mutable before being used.
So it may be possible to inject `ObjectMapper` on some entity you
control, modify that,
instead of trying to do the reverse.

-+ Tatu +-

>
>
> Cheers,
> -Kean
>
> On Mon, Nov 13, 2017 at 1:33 PM, Tatu Saloranta <ta...@fasterxml.com> wrote:
>>
>> Ok. If so it might make sense to first make sure that framework is
>> using properly configured mapper.
>> One way would be to create a simple stand-alone test with POJO,
>> outside of framework (JAX-RS?).
>> If I understood situation correctly it should just work. One thing I
>> don't know is why value would be serialized
>> as empty String -- I don't see how Jackson would ever produce that.
>>
>> Anyway: if stand-alone case fails as explained I'd like an issue filed
>> for the module since this use case
>> (reading JSON into org.json model; writing JSON out of org.json model)
>> is what module was written for.
>> So it should really "just work".
>>
>> -+ Tatu +-
>>

Kean Erickson

unread,
Nov 15, 2017, 6:22:09 PM11/15/17
to jackso...@googlegroups.com
Thanks you, Tatu. Unless I am misunderstanding, it does seem that my ObjectMapper with JsonOrgModule() is being used, given that I can print JSON properly in GET requests.
Is it necessary to have a provider class for the ObjectMapper which implements ContextResolver<ObjectMapper>? Or would that incur added overhead as you mentioned here?
https://github.com/FasterXML/jackson-jaxrs-providers/issues/86



On Tue, Nov 14, 2017 at 10:30 PM, Tatu Saloranta <ta...@fasterxml.com> wrote:
On Tue, Nov 14, 2017 at 6:22 PM, Kean Erickson <kean.e...@gmail.com> wrote:
> Hey there Tatu,
>
>
> So after adding a provider class extending JacksonJaxbJsonProvider, I've had
> success in producing JSONObjects over GET requests, but there's still some
> trouble still with interpreting POSTed json in requests as JSONObject. I was
> curious, should writing a custom MessageBodyReader still be necessary with
> JsonOrgModule in use?

It should work just fine for GETs, POSTs and PUTs. Should not require
custom MessageBodyReader.

Tatu Saloranta

unread,
Nov 15, 2017, 6:53:18 PM11/15/17
to jackson-user
On Wed, Nov 15, 2017 at 3:22 PM, Kean Erickson <kean.e...@gmail.com> wrote:
> Thanks you, Tatu. Unless I am misunderstanding, it does seem that my
> ObjectMapper with JsonOrgModule() is being used, given that I can print JSON
> properly in GET requests.
> Is it necessary to have a provider class for the ObjectMapper which
> implements ContextResolver<ObjectMapper>? Or would that incur added overhead
> as you mentioned here?
> https://github.com/FasterXML/jackson-jaxrs-providers/issues/86

I don't think your registering provider makes a big difference, as
long as you make sure to return singleton
mapper instance -- that is, if and when it is called for every request
make sure not to have to construct
new mapper every time.

As to whether that is necessary I honestly do not know. Maybe someone
else can help here.

-+ Tatu +-

Kean Erickson

unread,
Nov 15, 2017, 9:44:02 PM11/15/17
to jackso...@googlegroups.com
Thanks for all your help, I finally got it working both ways. Counter to what other guides have said, having a ContextMapper was not necessary, nor was having a class  "JacksonConfigFeature implements Feature".

Adding this singleton to my application (with extends JacksonJaxbJsonProvider and consumes + produces) was all that was needed.

@Provider
@Consumes(MediaType.APPLICATION_JSON)

@Produces(MediaType.APPLICATION_JSON)
public class JacksonConfigProvider extends JacksonJaxbJsonProvider {

    private final static ObjectMapper mapper =
                    new ObjectMapper()
                    .registerModule(new JsonOrgModule())
                    .registerModule(new JaxbAnnotationModule());

    JacksonConfigProvider() {
        super(mapper, JacksonConfigProvider.DEFAULT_ANNOTATIONS);
    }
}


No jersey-specific junk needed. I'm relieved, this was really difficult due to metric tonnes of misinformation online. Thanks again!

Tatu Saloranta

unread,
Nov 16, 2017, 12:03:16 AM11/16/17
to jackson-user
On Wed, Nov 15, 2017 at 6:43 PM, Kean Erickson <kean.e...@gmail.com> wrote:
> Thanks for all your help, I finally got it working both ways. Counter to
> what other guides have said, having a ContextMapper was not necessary, nor
> was having a class "JacksonConfigFeature implements Feature".
>
> Adding this singleton to my application (with extends
> JacksonJaxbJsonProvider and consumes + produces) was all that was needed.
>
> @Provider
> @Consumes(MediaType.APPLICATION_JSON)
> @Produces(MediaType.APPLICATION_JSON)
> public class JacksonConfigProvider extends JacksonJaxbJsonProvider {
>
> private final static ObjectMapper mapper =
> new ObjectMapper()
> .registerModule(new JsonOrgModule())
> .registerModule(new JaxbAnnotationModule());
>
> JacksonConfigProvider() {
> super(mapper, JacksonConfigProvider.DEFAULT_ANNOTATIONS);
> }
> }
>
> No jersey-specific junk needed. I'm relieved, this was really difficult due
> to metric tonnes of misinformation online. Thanks again!

Thank you for sharing this: it makes sense to me.

Yes, so much old/mis-information. And sometimes frameworks
adding wrapping around features like Jackson which tends to obfuscate
more straight-forward usage.

-+ Tatu +-

>
>
> On Wed, Nov 15, 2017 at 3:53 PM, Tatu Saloranta <ta...@fasterxml.com> wrote:
>>
>> On Wed, Nov 15, 2017 at 3:22 PM, Kean Erickson <kean.e...@gmail.com>
>> wrote:
>> > Thanks you, Tatu. Unless I am misunderstanding, it does seem that my
>> > ObjectMapper with JsonOrgModule() is being used, given that I can print
>> > JSON
>> > properly in GET requests.
>> > Is it necessary to have a provider class for the ObjectMapper which
>> > implements ContextResolver<ObjectMapper>? Or would that incur added
>> > overhead
>> > as you mentioned here?
>> > https://github.com/FasterXML/jackson-jaxrs-providers/issues/86
>>
>> I don't think your registering provider makes a big difference, as
>> long as you make sure to return singleton
>> mapper instance -- that is, if and when it is called for every request
>> make sure not to have to construct
>> new mapper every time.
>>
>> As to whether that is necessary I honestly do not know. Maybe someone
>> else can help here.
>>
>> -+ Tatu +-
>>
>> >
>

Kean Erickson

unread,
Dec 1, 2017, 2:21:18 PM12/1/17
to jackso...@googlegroups.com
Hey Tatu, I have one more question about JsonOrgModule.

I'm wondering if there's a way to distinguish whether the user sent a {} or an "".. that is, whether they sent the correct type. In both cases it comes through as {} for my setter, and I'm wondering if there's anything extra I can do to handle for user error, like throw an exception when the wrong type is provided. As a more general question, I'm wondering if there's any way to enforce strict typing (integers vs strings).

Tatu Saloranta

unread,
Dec 11, 2017, 3:00:41 PM12/11/17
to jackson-user
On Fri, Dec 1, 2017 at 11:21 AM, Kean Erickson <kean.e...@gmail.com> wrote:
> Hey Tatu, I have one more question about JsonOrgModule.
>
> I'm wondering if there's a way to distinguish whether the user sent a {} or
> an "".. that is, whether they sent the correct type. In both cases it comes
> through as {} for my setter, and I'm wondering if there's anything extra I
> can do to handle for user error, like throw an exception when the wrong type
> is provided. As a more general question, I'm wondering if there's any way to
> enforce strict typing (integers vs strings).

I am not 100% sure what handling you are referring to. JsonOrgModule does not
(as far as I remember) do any coercions but builds exact copy of
incoming JSON structure,
using methods org.json package has. So it should not change structure
in any way.

Jackson databind does allow many coercions (and there are some
`DeserializationFeature`s
for disabling most) however, if you might be referring to those.

-+ Tatu +-
Reply all
Reply to author
Forward
0 new messages