使用Jackson

时间:2017-04-02 00:00:10

标签: java json jackson

我使用Jackson Fasterxml版本2.8.0来序列化和反序列化json,如下所示:

public static byte[] serializeData(Object object){
   final ObjectMapper mapper = new ObjectMapper();
   return mapper.writeValueAsBytes(object);
}

public static void main(String [] args) {
  String json = "{ \"id\" : \"user1\" }"; // need to escape or else compiler complains

  byte[] result = serializeData(json);

  final ObjectMapper mapper = new ObjectMapper();
  final JsonNode jsonNode = mapper.readTree(result);

  System.out.println(json);
  System.out.println(jsonNode.toString());
  System.out.println(jsonNode.getNodeType());

  Iterator<String> fields = jsonNode.fieldNames();
  while(fields.hasNext()){
    System.out.println("field - " + fields.next());
  }
}

输出结果为:

{ "id" : "user1" }
"{ \"id\" : \"user1\" }"
STRING

请注意,没有用于打印字段名称的输出行。因此,似乎JsonNode没有任何属性,并且由于某种原因,toString()中包含了转义字符。我是以错误的方式使用这个库吗?为什么在反序列化字节数组时导致我无法找到我最初添加的字段的行为?

更新

提供更多应用程序的上下文。该应用程序接收Json作为String输入。反序列化Json的代码不知道Json的模型。它只是期望它是有效的Json对象,以便它可以遍历其中的各个字段。

2 个答案:

答案 0 :(得分:1)

您将JSON字符串误认为是java Object,这是此处的关键问题。

  String json = "{ \"id\" : \"user1\" }"; // need to escape or else compiler complains

  byte[] result = serializeData(json);

你的String json只是一个字符串,它的内容并不重要,使用mapper.writeValueAsBytes(object)只序列化一个字符串,从而产生一个STRING类型的单个JSON节点。

要序列化字段ID为String类型的Object,您需要序列化一个名为id String的字段的对象。

例如:

public class User {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "User [id=" + id + "]";
    }
}

此类型用户可以序列化为{"id":"User1"}(如果id字段设置为“User1”)。

在以下示例中,您可以从POJO(User user = new User();)开始,也可以从有效的json字符串(String json = "{ \"id\" : \"user1\" }";)开始。

在第一种情况下,您首先将对象映射到json字节,然后解析这些字节以获取JSONNode(json的一种DOM树)。

在第二种情况下,你只需要解析字节来获取节点,你就不会写出json字符串的值,因为你只需字符串化两次就可以获得STRING类型的值节点。

    User user = new User();
    user.setId("user1");

    ObjectMapper mapper = new ObjectMapper();
    byte[] jsonBytes = mapper.writeValueAsBytes(user);


    System.out.println(new String(jsonBytes)); // will print {"id":"user1"}

    JsonNode node = mapper.readTree(jsonBytes);
    Iterator<String> names = node.fieldNames();
    while (names.hasNext()) {
        String name = (String) names.next();
        JsonNodeType type = node.get(name).getNodeType();
        System.out.println(name+":"+type); //will print id:STRING
    }

    // This is not a object to serialize 
    // This is a string to parse into a json object
    String json = "{ \"id\" : \"user1\" }";

    JsonNode node2 = mapper.readTree(json.getBytes());
    names = node.fieldNames();
    while (names.hasNext()) {
        String name = (String) names.next();
        JsonNodeType type = node.get(name).getNodeType();
        System.out.println(name+":"+type); //will print id:STRING
    }

答案 1 :(得分:0)

这是因为你在toString()方法中调用writeValueAsBytes将对象转换为字符串。以下应该可以正常工作:

final ObjectMapper mapper = new ObjectMapper();
ObjectNode node = JsonNodeFactory.instance.objectNode();
node.put("id", "user1");
byte[] result = mapper.writeValueAsBytes(node);
final JsonNode json = mapper.readTree(result);
System.out.println(json);
Iterator<String> fieldNames = json.fieldNames();
while(fieldNames.hasNext()){
    System.out.println(fieldNames.next());
}
if(json.has("id")){
  System.out.println("No id");
}

<强>更新

如果您不知道要将json反序列化的对象类型,那么您可以将其反序列化为Map,例如:

Map<String, Object> result = mapper.readValue(result, new TypeReference<Map<String,Object>>() {});