7

How do I have JAXB preserve nulls when receiving a JSON sting that contains a null or "" value.

String:{"id":null,"fname":"John","region":""}

returns Object:

 Person {
    Integer id = 0
    String fname = "John"
    Region regions = 0 }

I would like it to return null instead of 0

Here is what I have so far:

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    private JAXBContext context;
    private Class<?>[] types = {Person.class};

    public JAXBContextResolver() throws Exception {
        this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), types);
    }

    public JAXBContext getContext(Class<?> objectType) {
        for (Class<?> c : types) {
            if (c.equals(objectType)) {
                return context;
            }
        }
        return null;
    }
}

Person.class is annotated with @XmlRootElement I've tried looking into Jackson annotations but have had no success.

Jaym
  • 301
  • 5
  • 14
  • Same problem here. Someone got a solution for this problems. The ObjectMapper seems to be ignored by Jersey – keatch Jan 19 '12 at 10:26
  • Same problem as well. I also tried using ObjectMapper and Jersey failed to pick it up as well. I'm not sure that using ObjectMapper is the simplest solution anyway... – Oleksi May 02 '12 at 20:10
  • 1
    My similar issue has been resolved. You can see if it helps you...http://stackoverflow.com/questions/10420641/including-null-elements-in-json-output-of-jersey-restful-api-with-jaxb – Oleksi May 03 '12 at 19:58

2 Answers2

4

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

Below is an example of how this can be done with MOXy.

Person

MOXy will unmarshal the Person object as you want without specifying any metadata. To have the output JSON contain null values, you can use the @XmlElement(nillable=true) annotation (see Binding to JSON & XML - Handling Null).

package forum8748537;

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Person {

    @XmlElement(nillable=true)
    Integer id;

    @XmlElement(nillable=true)
    String fname;

    @XmlElement(nillable=true)
    Region regions;

}

jaxb.properties

To specify MOXy as your JAXB (JSR-222) provider you need to add a file called jaxb.properties in the same package as your domain classes with the following entry (see Specifying EclipseLink MOXy as Your JAXB Provider).

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Demo

package forum8748537;

import java.io.StringReader;
import java.util.*;

import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(2);
        properties.put("eclipselink.media-type", "application/json");
        properties.put("eclipselink.json.include-root", false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Person.class}, properties);

        StringReader json = new StringReader("{\"id\":null,\"fname\":\"John\",\"region\":\"\"}");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Person person = unmarshaller.unmarshal(new StreamSource(json), Person.class).getValue();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(person, System.out);
    }

}

Output

{
   "id" : null,
   "fname" : "John",
   "regions" : null
}

Using MOXy in a JAX-RS Application

For an example of using MOXy in a JAX-RS application see:

bdoughan
  • 147,609
  • 23
  • 300
  • 400
1

As of JSON-B JSR-367 (JAX-RS 2.1 JSR-370), the following annotation works instead of @XmlElement.

@JsonbProperty(nillable = true)
Hirofumi Okino
  • 975
  • 1
  • 10
  • 22