使用杰克逊在带有嵌套JSON的对象之间进行转换

时间:2018-11-01 15:17:19

标签: java json serialization jackson deserialization

我下面有一个带有两个String字段的Entity类:名称和描述。 description字段包含原始JSON值,例如{“ abc”:123}

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

    @JsonRawValue
    private String descriptionJson; 
}

我下面使用Jackson进行序列化和反序列化得到了简单的测试代码:

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);

转换对象-> JSON时,由于设置了@JsonRawValue,因此描述字符串是嵌套的:

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

但是,当我调用Jackson的mapper.readValue函数将JSON字符串读回到实体对象时,我得到了一个例外:

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"])

鉴于存在@JsonRawValue批注,您如何建议将创建的JSON字符串编组回Entity对象?我还有其他注释吗?

谢谢

4 个答案:

答案 0 :(得分:0)

您可以按以下方式使用Jackson 2中的ObjectMapper

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

尝试转义描述json值中的花括号。

答案 1 :(得分:0)

@JsonRawValue仅用于从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.

进行串行化

要解决您的问题,您可以尝试

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();
    }
}

答案 2 :(得分:0)

@JsonRawValue仅用于序列化端,但是在此问题中,您可以这样操作:

@Getter
@Setter
public class Entity {

    private String name;

    @JsonRawValue
    private String descriptionJson;

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

重复出现此问题 How can I include raw JSON in an object using Jackson?

答案 3 :(得分:0)

对于我的要求之一,我使用字段类型作为Map来按原样存储Json。这样,我就可以将嵌套的JSOn读取为Map,并且在将对象序列化为JSON时,它可以正确显示。下面是示例。

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"
  }
}