Adam
Adam

Reputation: 532

Using Jackson to convert to and from an object with nested JSON

I have an Entity class below with two String fields: name and description. The description field is to contain a raw JSON value e.g. { "abc": 123 }

@Getter
@Setter
public class Entity {
    private String name;

    @JsonRawValue
    private String descriptionJson; 
}

I've got simple test code below using Jackson to serialize and deserialize:

Entity ent = new Entity();
ent.setName("MyName");
ent.setDescriptionJson("{ \"abc\": 123 }");

// Convert Object to JSON string
String json = mapper.writeValueAsString(ent);

// Convert JSON string back to object
Entity ent2 = mapper.readValue(json, Entity.class);

When converting Object -> JSON the description string is nested because the @JsonRawValue is set:

{"name":"MyName","descriptionJson":{ "abc": 123 }}

However, when I call the Jackson mapper.readValue function to read the JSON string back into an entity object I get the exception:

com.fasterxml.jackson.databind.exc.MismatchedInputException:
Cannot deserialize instance of `java.lang.String` out of START_OBJECT token 
at [Source: (String)"{"name":"MyName","descriptionJson":{ "abc": 123 }}"; line: 1, column: 36] (through reference chain: com.test.Entity["descriptionJson"])

Given that the @JsonRawValue annotation exists, how would you recommend marshalling the created JSON string back into to Entity object? Is there another annotation I'm missing?

Thanks

Upvotes: 4

Views: 11748

Answers (4)

Juan Rada
Juan Rada

Reputation: 3766

@JsonRawValue is intended only sor serializatio from docs:

Marker annotation that indicates that the annotated method or field should be serialized by including literal String value of the property as is, without quoting of characters.

To solve your problem you can try

public class Entity {
    @Getter
    @Setter
    private String name;

    private String descriptionJson;

    @JsonRawValue
    public String getDescriptionJson() {
        return descriptionJson;
    }

    public void setJson(JsonNode node) {
        this.descriptionJson = node.toString();
    }
}

Upvotes: 0

nonysingh
nonysingh

Reputation: 91

For one of my requirements I used field type as Map to store Json as it is. This way I was able to read the nested JSOn as Map and when I serialize object to JSON, it came up correctly. Below is the example.

Entity.java

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Entity {
    public int id=0;
    public String itemName="";
    public Map<String,String> owner=new HashMap<>();
}

Temp.java

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public class Temp {

public static void main(String[] args){

    ObjectMapper objectMapper= new ObjectMapper();
    try {
        Entity entity 
=objectMapper.readValue(Temp.class.getResource("sample.json"), Entity.class);
        System.out.println(entity);
        String json=objectMapper.writeValueAsString(entity);
        System.out.println(json);
    } catch (IOException e) {
        e.printStackTrace();
    }


    }
}

Sample.json

{
  "id": 1,
  "itemName": "theItem",
  "owner": {
    "id": 2,
    "name": "theUser"
  }
}

Upvotes: 1

iceqing
iceqing

Reputation: 1103

@JsonRawValue is intended for serialization-side only, but in this problem you can do like this:

@Getter
@Setter
public class Entity {

    private String name;

    @JsonRawValue
    private String descriptionJson;

    @JsonProperty(value = "descriptionJson")
    public void setDescriptionJsonRaw(JsonNode node) {
        this.descriptionJson = node.toString();
    }
}

This problem is repeated with How can I include raw JSON in an object using Jackson?.

Upvotes: 4

You can use ObjectMapper from Jackson 2 as follows:

ObjectMapper mapper = new ObjectMapper();
String jsonStr = "sample json string"; // populate this as required
MyClass obj = mapper.readValue(jsonStr,MyClass.class)

try escaping the curly braces in the description json's value.

Upvotes: 0

Related Questions