Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Jersey/Jackson serialize empty list; single element list as an array

Using Jersey and Jackson to create a REST interface, how do I get List fields to be serialized as a list when there are 0 or 1 elements in them. For example:

@XmlRootElement(name="foo")
public class Foo {
  @XmlElement
  public List<Bar> getBars() {
    return this.bars;
  }
}

@Path("foo")
public FooResource {
  @GET
  public Foo getFoo() {
    return theFoo;
  }
}

When bars has no elements, the result serializes as null and when it contains a single element, it serializes as that element, not an array containing a single element. Is there a way to get these to always serialize as an array?

For reference, I'm using Jersey 1.10 and Jackson 1.9.2.

like image 837
Brandon DuRette Avatar asked Nov 21 '11 16:11

Brandon DuRette


2 Answers

I am pretty sure that you are not actually using Jackson ("POJO" variant of JSON serialization), since Jackson would not convert single-element arrays or lists to anything else. So you are probably using one of legacy output methods (like jettison); meaning that if you configure system to use POJO mapping it should just work.

like image 130
StaxMan Avatar answered Sep 28 '22 04:09

StaxMan


I wrote a blog post ages ago about forcing Jersey to serialize single element arrays correctly, not sure if it's out-dated now (its from mid-2010!), but it might be of use.

Note the blog comment from Brill Pappin on the blog demonstrating a different approach which means upgrading the Jettison library that you are using.

In short you can write a custom JaxbContextResolver that looks a little like:

@Provider
@Component
public class JAXBContextResolver implements ContextResolver {

    private JAXBContext context;

    public JAXBContextResolver() throws Exception {
        MappedBuilder builder = JSONConfiguration.mapped();
        builder.arrays("invite");
        builder.rootUnwrapping(true);
        this.context = new JSONJAXBContext(builder.build(), Payload.class);
    }

    public JAXBContext getContext(Class objectType) {
        return (Payload.class.equals(objectType)) ? context : null;
    }
}

For clarity, my payload class looked a little like

@XmlRootElement(name = "response")
@XmlAccessorType(XmlAccessType.FIELD)
public class Payload {

    @XmlElement(name = "invite")
    List invites;

    ... etc.

Regarding stopping Jackson serializing bean properties as null, see my previous answer here, about using annotations to change that behaviour.

like image 38
Derek Troy-West Avatar answered Sep 28 '22 04:09

Derek Troy-West