1

I'm using jax-rs and adding entity for being marshalled in Jetty by JAXRSOutInterceptor, but JSON output is being modified with additional empty property which looks like this: "$": ""

The JSONProvider is created and configured as here:

JSONProvider jsonProvider = new JSONProvider();
jsonProvider.setConvertTypesToStrings(true);
jsonProvider.setIgnoreNamespaces(true);
jsonProvider.setIgnoreMixedContent(true);
jsonProvider.setUnmarshallAsJaxbElement(true);
providers.add(jsonProvider);

It is also being marshalled to XML which uses namespaces but I don't want them in JSON output and input.

The object that is being marshalled is similar to this:

@XmlRootElement(name="myObject1")
@XmlAccessorType(XmlAccessType.FIELD)
@SuppressWarnings("serial")
public class MyObject1 implements Serializable {

    MyObject2 a;
    MyObject2 b;
    MyObject2 c;

// includes getters, setters, hashCode, equals, toString,   
}

When MyObject2 is:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@SuppressWarnings("serial")
public class MyObject2 implements Serializable {

    String x;
    String y;
    List<String> z;

// includes getters, setters, hashCode, equals, toString,   
}

The rest output is as following:

{
   "myObject1": {
      "a": {
         "x": "value1",
         "y": "value2",
         "z": "value3",
         "$": ""
      },
      "$": ""
   }
}

How do I get rid of the ending "$": "" I read that the Jettison (which is the default JSONProvider implementation that I am using) is by default will represent properties mapped with @XmlValue as '$'s but there's no property ?

Is that caused by implementing Serializable?

bdoughan
  • 147,609
  • 23
  • 300
  • 400
mik80
  • 25
  • 2
  • 8

1 Answers1

1

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

Jettison isn't really a JSON provider but an API that can allow XML libraries to produce/consume JSON. It does a decent job, but there are problems that can occur like the one you are experiencing now. You are also seeing the issues where lists of size one are not marshalled as JSON arrays.

If you can't find a way to make this work with your current set up. Below is what you could do with MOXy as your JSON provider:

MyObject1

package forum11262807;

import java.io.Serializable;
import javax.xml.bind.annotation.*;

@XmlRootElement(name="myObject1")
@XmlAccessorType(XmlAccessType.FIELD)
@SuppressWarnings("serial")
public class MyObject1 implements Serializable {

    MyObject2 a;
    MyObject2 b;
    MyObject2 c;

}

MyObject2

package forum11262807;

import java.io.Serializable;
import java.util.List;
import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@SuppressWarnings("serial")
public class MyObject2 implements Serializable {

    String x;
    String y;
    List<String> z;

}

jaxb.properties

To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry:

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

Demo

Below is some standalone code to demonstrate the reading/writing of the JSON.

package forum11262807;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.setProperty("eclipselink.media-type", "application/json");
        File json = new File("src/forum11262807/input.json");
        MyObject1 myObject1 = (MyObject1) unmarshaller.unmarshal(json);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty("eclipselink.media-type", "application/json");
        marshaller.marshal(myObject1, System.out);
    }

}

input.json/Output

The resulting JSON message contains no "$" properties and the list of size 1 is property represented as a JSON array.

{
   "myObject1" : {
      "a" : {
         "x" : "value1",
         "y" : "value2",
         "z" : [ "value3" ]
      }
   }
}

JAX-RS Integration

MOXy includes the MOXyJsonProvider class that makes it easy to configure in your JAX-RS application:

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • 1
    Thanks, btw I saw your blog before (nice one), when I've tried to search a solution to my issue, I just didn't want to change the json provider right now since I'm at the end of the project sprint. I'll try with moxy next. – mik80 Jun 29 '12 at 19:41
  • It was what you wrote, the z list contained a single element which was an empty string, I don't know where did it come from, the object was a jettison product of unmarshalled xml which I had to return from my rest method in json format. I've ended with jackson but it was not an easy go, again. – mik80 Jul 03 '12 at 14:52