4

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

Adam
  • 532
  • 3
  • 11
  • 22

4 Answers4

4

@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?.

iceqing
  • 955
  • 11
  • 12
1

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"
  }
}
nonysingh
  • 71
  • 1
  • 6
0

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.

0

@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();
    }
}
svick
  • 236,525
  • 50
  • 385
  • 514
Juan Rada
  • 3,513
  • 1
  • 26
  • 26