how to force jettison to write an array, even if there is only one element in the array?
Asked Answered
M

1

24

With the simplified example below:

I get the following, as expected:

{"person":{"name":"john","tags":["tag1","tag2"]}}

However, if I only set one tag, I get this:

{"person":{"name":"john","tags":"tag1"}}

And I was expecting to get this:

{"person":{"name":"john","tags":["tag1"]}}

That is, jettison has removed the array for tags, because there is only one element in the array.

I think this is pretty unsafe.

How to force jettison to write an array, even if there is only one element?

Note: I am aware that there are other alternatives to jettison, such as StAXON. However, here I am asking how to achieve this using Jettison. Please do not suggest another alternative to jettison.

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.*;

import java.io.*;
import javax.xml.bind.*;
import javax.xml.stream.XMLStreamWriter;
import org.codehaus.jettison.mapped.*;


public class JettisonTest {
    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Person.class);

        Person person = new Person();
        person.name = "john";
        person.tags.add("tag1");
        person.tags.add("tag2");

        Configuration config = new Configuration();
        MappedNamespaceConvention con = new MappedNamespaceConvention(config);
        Writer writer = new OutputStreamWriter(System.out);
        XMLStreamWriter xmlStreamWriter = new MappedXMLStreamWriter(con, writer);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.marshal(person, xmlStreamWriter);
    }
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Person {
    String name;
    List<String> tags = new ArrayList<String>();
}
Macur answered 10/12, 2012 at 17:21 Comment(2)
So were you able to solve the problem after all?Saurel
No. I ended up replacing Jettison by Jackson.Macur
L
1

I found this: https://blogs.oracle.com/japod/entry/missing_brackets_at_json_one

It seems that adding a line to your context resolver to explicitly state that tags is an array is the way to do this; i.e.

props.put(JSONJAXBContext.JSON_ARRAYS, "[\\"tags\\"]");

NB: I'm not familiar with Jettison, so have no personal experience to back this up; only the info on the above blog post.

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {

    private JAXBContext context;
    private Class[] types = {ArrayWrapper.class};

    public JAXBContextResolver() throws Exception {
        Map props = new HashMap<String, Object>();
        props.put(JSONJAXBContext.JSON_NOTATION, "MAPPED");
        props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.TRUE);

        props.put(JSONJAXBContext.JSON_ARRAYS, "[\\"tags\\"]"); //STATE WHICH ELEMENT IS AN ARRAY

        this.context = new JSONJAXBContext(types, props);
    }

    public JAXBContext getContext(Class<?> objectType) {
        return (types[0].equals(objectType)) ? context : null;
    }

}
Ligni answered 5/11, 2016 at 9:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.