Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 324
Adam Avatar asked Sep 01 '25 02:09

Adam


2 Answers

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

like image 100
iceqing Avatar answered Sep 02 '25 17:09

iceqing


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"
  }
}
like image 25
nonysingh Avatar answered Sep 02 '25 17:09

nonysingh