Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON - Unable to serialize JSONObject within Object using Jackson

I have the following class:

class A{    
    String abc;
    String def;
    // appropriate getters and setters with JsonProperty Annotation 
}

and I call Jacksons objectMapper.writeValueAsString(A) which works fine.

Now I need to add another instance member:

class A{    
    String abc;
    String def;
    JSONObject newMember; // No, I cannot Stringify it, it needs to be JSONObject
    // appropriate getters and setters with JsonProperty Annotation 
}

but when I serialize, I am getting exception:

org.codehaus.jackson.map.JsonMappingException: No serializer found for class org.json.JSONObject and no properties discovered to create BeanSerializer

I tried JSONNode but it gave Output as {outerjson:"{innerjson}"} not {outerjson:{innerjson}}.

Is it possible to use Jackson to achieve the above output, i.e. JSONObject within JSONObject?

enter image description here

like image 721
dev ray Avatar asked Apr 29 '14 14:04

dev ray


People also ask

What is Jackson object serialization?

Jackson is a solid and mature JSON serialization/deserialization library for Java. The ObjectMapper API provides a straightforward way to parse and generate JSON response objects with a lot of flexibility.

Does Jackson use Java serialization?

Note that Jackson does not use java. io. Serializable for anything: there is no real value for adding that. It gets ignored.

How does Jackson deserialize dates from JSON?

In order to correct deserialize a Date field, you need to do two things: 1) Create a custom deserializer by extending StdDeserializer<T> class and override its deserialize(JsonParser jsonparser, DeserializationContext context) method. This method should return a Date if we are using this to parse a date field in JSON.


2 Answers

What about to use jackson-datatype-json-org

// import com.fasterxml.jackson.datatype.jsonorg.JsonOrgModule;

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JsonOrgModule());

See https://github.com/FasterXML/jackson-datatype-json-org

like image 190
banterCZ Avatar answered Oct 21 '22 00:10

banterCZ


Well, if you cannot replace the JSONObject on a POJO or a Map, then you can write a custom serializer. Here is an example:

public class JacksonJSONObject {

    public static class MyObject {
        public final String string;
        public final JSONObject object;

        @JsonCreator
        public MyObject(@JsonProperty("string") String string, @JsonProperty("object") JSONObject object) {
            this.string = string;
            this.object = object;
        }

        @Override
        public String toString() {
            return "MyObject{" +
                    "string='" + string + '\'' +
                    ", object=" + object +
                    '}';
        }
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule("org.json");
        module.addSerializer(JSONObject.class, new JsonSerializer<JSONObject>() {
            @Override
            public void serialize(JSONObject value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
            jgen.writeRawValue(value.toString());
            }
        });
        module.addDeserializer(JSONObject.class, new JsonDeserializer<JSONObject>() {
            @Override
            public JSONObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
                Map<String, Object> bean = jp.readValueAs(new TypeReference<Map<String, Object>>() {});
                return new JSONObject(bean);
            }
        });
        mapper.registerModule(module);
        JSONObject object = new JSONObject(Collections.singletonMap("key", "value"));
        String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(new MyObject("string", object));

        System.out.println("JSON: " + json);
        System.out.println("Object: " + mapper.readValue(json, MyObject.class));
    }
}

Output:

JSON: {
  "string" : "string",
  "object" : {"key":"value"}
}
Object: MyObject{string='string', object={"key":"value"}}
like image 26
Alexey Gavrilov Avatar answered Oct 21 '22 02:10

Alexey Gavrilov