writeXsiType=false gives the output I listed in my previous email. Its probably 
ok for what I need to do but the "" seems to imply that "id" is a String rather 
than a number. Maybe the json parser that will convert that back into a 
Java/.NET object will be forgiving and do the right thing. Adding some sort of 
omitNullValues could help reduce the payload over the wire for large lists of 
objects that contain mostly uninitialized properties. I don't know enough about 
CXF to comment if that should be on the built-in JSONProvider.


I'm trying to retrofit an existing JAX-WS application (along with its jaxb 
annotated generated entities) with JAX-RS support. I don't have the luxury of 
being able to change the JAX-WS generated code. I'm finding that the jaxb 
annotations are getting in the way...especially since many of the entities I 
want to return in my JAX-RS code don't have XmlRootElement on them. Using the 
GsonProvider below on both the server and client seems to bypass all the jaxb 
stuff like I want (at least for producing entities, I haven't tried consuming 
yet):


//inspired by 
http://code.google.com/p/derquinse-commons/.../GenericGsonProvider.java
@Provider
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class GsonProvider extends MessageBodyReaderWriter
{
    @Override
    protected void writeTo(Object item, Type type, Writer writer) throws 
Exception {
        getGson().toJson(item, type, writer);                    
    }        
    
    @Override
    protected Object readFrom(Reader reader, Type type) throws IOException, 
WebApplicationException {            
        return getGson().fromJson(reader, type);        
    }
    
    private Gson getGson() {
        return new GsonBuilder().create();
    }
}

I read through JSONProvider, AbstractJAXBProvider, and lots of the CXF test 
cases. My GsonProvider class is bypassing 1,200+ lines of code in the built-in 
CXF providers. Can you spot any obvious short-comings with my approach? 
MessageBodyReaderWriter is just boiler plate code that implements the 
interfaces for Object.

Thanks,
Ron


________________________________
 From: Sergey Beryozkin <[email protected]>
To: [email protected] 
Sent: Sunday, April 15, 2012 4:14 PM
Subject: Re: JAX-RS in v2.5.x: how to set custom JSONProvider(?) without Spring 
to stop {"@xsi.nil":"true"}
 
On 15/04/12 21:07, Ron Grabowski wrote:
> I have a feeling this is the best I can do with writeXsiType=false?
>
> {"widget":{"id":"","name":"Hello World"}}
>
Is it what is happening after you've configured this option ?
> There isn't a built-in option to omit the "id" entry entirely or set it to 
> null?
>
you may also want to experiment with the CXF Transformation Feature 
which does work with JSONProvider, but configuring this feature without 
Spring may be tricky

As I said, you may also try other JSON providers if needed

Sergey
>
>
> ________________________________
>   From: Sergey Beryozkin<[email protected]>
> To: [email protected]
> Sent: Sunday, April 15, 2012 2:22 PM
> Subject: Re: JAX-RS in v2.5.x: how to set custom JSONProvider(?) without 
> Spring to stop {"@xsi.nil":"true"}
>
> Hi
> On 15/04/12 19:09, Ron Grabowski wrote:
>> This post was helpful in showing how to set a custom JSONProvider both with 
>> and without Spring:
>>
>>
>> http://stackoverflow.com/a/6344047
>>
>
> You can do:
>
> <init-param>
>     <param-name>jaxrs.providers</param-name>
>     <param-value>
>         org.apache.cxf.jaxrs.provider.JSONProvider
>         (writeXsiType=false)
>     </param-value>
> </init-param>
>
> I updated that thread too
>
>> I'm assuming custom providers are registered before or override the built-in 
>> ones so they get to inspect things first?
>>
>
> Yes
>
>> Here's some test cases explaining what I'm trying to do:
>>
>>
>> @Test // passes
>> public void JSONProviderIncludesNil() throws Exception {
>>        JSONProvider p = new JSONProvider();
>>        Widget widget = new Widget();
>>        widget.setName("Hello World");
>>        String json = toJson(p, widget, "widget", Widget.class);
>>        
>>assertEquals("{\"widget\":{\"id\":{\"@xsi.nil\":\"true\"},\"name\":\"Hello 
>>World\"}}", json);
>> }
>>
>> @Test // fails
>> public void OmitNillJSONProviderExcludesNil() throws Exception {
>>        JSONProvider p = new OmitNillJSONProvider();
>>        Widget widget = new Widget();
>>        widget.setName("Hello World");
>>        String json = toJson(p, widget, "widget", Widget.class);
>>        assertEquals("{\"widget\":{\"name\":\"Hello World\"}}", json);
>> }
>>
>> private<T>   String toJson(JSONProvider p, T item, String root, Class<T>   
>> classOfT) throws Exception {
>>        ByteArrayOutputStream stream = new ByteArrayOutputStream();
>>        p.writeTo(
>>            new JAXBElement<T>(new QName("", root), classOfT, item), // hack 
>>???
>>            classOfT, classOfT,
>>            classOfT.getAnnotations(),
>>            MediaType.APPLICATION_JSON_TYPE,
>>            new MetadataMap<String, Object>(),
>>            stream);
>>        return stream.toString();
>> }
>>
>> // yes, I know XmlRootElement is missing
>> @XmlAccessorType(XmlAccessType.FIELD)
>> @XmlType(name = "widget", propOrder = {"id","name"})
>> public static class Widget {
>>        @XmlElement(nillable = true) // can't change
>>        protected Integer id;
>>        @XmlElement(nillable = true) // can't change
>>        protected String name;
>>        public Integer getId() {
>>            return id;
>>        }
>>        public void setId(Integer id) {
>>            this.id = id;
>>        }
>>        public String getName() {
>>            return name;
>>        }
>>        public void setName(String name) {
>>            this.name = name;
>>        }
>> }
>>
>> public class OmitNillJSONProvider extends JSONProvider {
>>        // ???
>> }
>>
>> Maybe I should bypass all this jaxb annotation sillyness and just let gson 
>> handle serializing the object as if it didn't have any annotations?
>>
>
> JSONProvider is a default provider but if some other JSON provider can
> handle this situation better, with or without JAXB, then it can be
> easily registered too
>
> HTH, Sergey
>>
>>
>> ________________________________
>>     From: Ron Grabowski<[email protected]>
>> To: "[email protected]"<[email protected]>
>> Sent: Saturday, April 14, 2012 10:17 PM
>> Subject: JAX-RS in v2.5.x: how to set custom JSONProvider(?) without Spring 
>> to stop {"@xsi.nil":"true"}
>>
>> I have objects with fields setup like this:
>>
>>     @XmlElement(nillable = true)
>>     protected Integer id;
>>
>> that I send out via JAX-RS with @Produces(MediaType.APPLICATION_JSON). The 
>> json payload ends up like this when the fields aren't set:
>>
>>
>>     "id":{"@xsi.nil":"true"}
>>
>> I can't change the @XmlElement on the field because another part of my 
>> system depends on it. I want to either output:
>>
>>     "id" : null
>>
>> or ideally not output that field at all in the json payload. I think I need 
>> extend the built in JSONProvder and tweak it (and/or Jettison) a little bit.
>>
>>
>> How can I do that without Spring? Can someone explain a solution both in 
>> terms of web.xml and JAXRSServerFactoryBean (unit testing)?
>>
>> Thanks,
>> Ron
>
>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Reply via email to