如何使用jackson将带有json值的Map <string,string =“”>转换为POJO?

时间:2016-03-14 20:06:02

标签: java jackson

我需要将java对象转换为Map<String, String>以获取我正在编写的REST api包装器。任何复杂对象的字段都需要序列化为json。我想出了如何做到这一点:

public static Map<String, String> toContentMap(Object object) throws JsonProcessingException {
    Map<String, Object> objectParamMap = MAPPER.convertValue(object, new TypeReference<Map<String, Object>>() {});
    Map<String, String> contentMap = new HashMap<>();

    for (Entry<String, Object> entry : objectParamMap.entrySet()) {
        String key = entry.getKey();
        String value = MAPPER.writeValueAsString(entry.getValue());
        contentMap.put(key, StringUtils.strip(value, "\""));
    }

    return contentMap;
}

现在我需要一种方法从这个Map<String, String>表示回到pojo对象。这可能主要使用jackson apis吗?

编辑:

我想我不清楚。我知道我要来往的POJO。但它应该是通用的,适用于任何基本的POJO。

一个例子:

class MyObject {
    String fieldA;
    Long fieldB;
    MyOtherObject fieldC;
    List<String> fieldD;
}

class MyOtherObject {
    String fieldA;
    String fieldB;
}

MyObject object = new MyObject("valueA", 20L, 
        new MyOtherObject("valueA", "valueB"), 
        Lists.newArrayList("array1", "array2"));

Map<String, String> contentMap = toContentMap(object);
/*
"fieldA" -> "valueA"
"fieldB" -> "20"
"fieldC" -> "{\"fieldA\":\"valueA\",\"fieldB\":\"valueB\"}"
"fieldD" -> "[\"array1\",\"array2\"]"
*/

MyObject newObject = fromContentMap(contentMap);
assertEquals(object, newObject)

3 个答案:

答案 0 :(得分:1)

您可以使用

ObjectMapper mapper = new ObjectMapper();
String jsonInString = "{'name' : 'rahul'}";


//JSON from String to Object
User user = mapper.readValue(jsonInString, User.class);

User user = mapper.convertValue(map, User.class);

如果要从json / map转换为自定义对象。您还可以将类型信息传递给序列化/反序列化过程,以便jackson知道内部。请详细了解here

答案 1 :(得分:1)

根据您的评论

  

它应该适用于我要求的任何POJO

我认为您正在寻找@JsonAnyGetter@JsonAnySetter注释,它会将它可以分配给POJO的值(您需要在反序列化时指定...它可以&#39;是通用的),但会将未解析的任何内容粘贴到Map<String, Object>

请注意,它不能是Map<String, String>,因为JSON不仅包含字符串作为其值。

例如,采用JSON

{
  "uid": 1,
  "username": "steve",
  "email": "steve@example.com"
}

你可以generate a Jackson POJO看起来像这样。

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
        "uid",
        "username",
        "email"
})
public class User {

    @JsonProperty("uid")
    private Integer uid;
    @JsonProperty("username")
    private String username;
    @JsonProperty("email")
    private String email;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    @JsonProperty("uid")
    public Integer getUid() {
        return uid;
    }

    @JsonProperty("uid")
    public void setUid(Integer uid) {
        this.uid = uid;
    }

    @JsonProperty("username")
    public String getUsername() {
        return username;
    }

    @JsonProperty("username")
    public void setUsername(String username) {
        this.username = username;
    }

    @JsonProperty("email")
    public String getEmail() {
        return email;
    }

    @JsonProperty("email")
    public void setEmail(String email) {
        this.email = email;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

}

答案 2 :(得分:0)

我害怕,我们无法做到。当object被序列化为JSON String时,它会丢失它的类类型。因此,在将字符串反序列化为对象时,解析器不知道要将对象反序列化的类。但是,有几种方法可以做到:

在另一张地图中存储类型信息:

像这样创建一个新的map

Map<String, Class> metaData = new HashMap<>();

它将类型名称与Class一起存储。因此,在派生时,我们可以从此地图中查找类类型并将其传递给readValue方法。

使用@Type的{​​{1}}注释:(仅当所有对象都扩展相同的基类时才有用)

Jakson有一个名为ObjectMapper的功能,如果所有类都继承了公共基类,它将有助于反序列化为对象。请查看文档here