使用Java的Jackson中的通用对象序列化

时间:2022-02-22 18:02:28

I would like to read in the string {"a": 1.0} as a generic Java Object while keeping the same string format. However, when I try, Jackson automatically changes the internal representation to {a = 1}. In other words, how can I get the following code to print {"a": 1.0} instead of {a = 1}? Note that, I have to read it in as an Object (due to other program constraints).

我想在字符串{“a”:1.0}中读取通用Java对象,同时保持相同的字符串格式。但是,当我尝试时,杰克逊自动将内部表示更改为{a = 1}。换句话说,如何让以下代码打印{“a”:1.0}而不是{a = 1}?请注意,我必须将其作为Object读取(由于其他程序限制)。

import org.codehaus.jackson.map.ObjectMapper;

public class Main {

    public static void main(String[] args) {
        try
    {
            ObjectMapper mapper = new ObjectMapper();
            Object myObject = mapper.readValue("{\"a\": 1.0}", Object.class);
            System.out.println(myObject.toString());            
    }
    catch (Exception e)
    {
        e.printStackTrace();
      System.err.println(e.getMessage()); 
    }
    }

}

4 个解决方案

#1


7  

The created object will be a map (like the other comments) and so its toString produces what you're seeing, {a = 1}. To get your code to print something closer to your input value, you need to use Jackson to write it back out with something like:

创建的对象将是一个地图(就像其他注释一样),因此它的toString会产生您所看到的内容,{a = 1}。要让代码打印出更接近输入值的代码,您需要使用Jackson将其写回来,例如:

System.out.println(mapper.writeValueAsString(myObject));

That gives me what I believe you're looking for:

这给了我相信你正在寻找的东西:

{"a":1.0}

In other words, Jackson has deserialized your input string into an arbitrary Java object. When you call toString on the object, its own toString is, of course, used. This can write the object however it pleases, including using the method from Object. To reproduce the input string, you have to use Jackson to serialize our object back out.

换句话说,Jackson已将您的输入字符串反序列化为任意Java对象。当你在对象上调用toString时,当然会使用它自己的toString。这可以写它喜欢的对象,包括使用Object中的方法。要重现输入字符串,您必须使用Jackson将我们的对象序列化。

#2


3  

You need an existing class that matches the desired json structure. Object is not such class. You can still refer to it as Object, if that's needed:

您需要一个与所需json结构匹配的现有类。对象不是这样的类。如果需要,您仍然可以将其称为Object:

Object myObject = mapper.readValue("{\"a\": 1.0}", SomeClass.class);

#3


2  

If you use a debugger, you will see that the type of the returned Object is LinkedHashMap. So what you see is the output of LinkedHashMap.toString(). There's no way for Jackson to change that, so you can either cast it to a Map and create the String yourself or ask for another return type that generates the JSON String for you:

如果使用调试器,您将看到返回的Object的类型是LinkedHashMap。所以你看到的是LinkedHashMap.toString()的输出。杰克逊没有办法改变它,所以你可以将它转换为Map并自己创建String或者请求另一个为你生成JSON字符串的返回类型:

if(myObject instanceof Map<?, ?>){
    final Map<?, ?> map = (Map<?, ?>) myObject;
    final StringBuilder sb = new StringBuilder("{");
    boolean first = true;
    for(final Entry<?, ?> entry : map.entrySet()){
        if(first){
            first = false;
        } else{
            sb.append(",");
        }
        sb.append("\n\t'")
            .append(entry.getKey())
            .append("':'")
            .append(entry.getValue())
            .append("'");
    }
    if(!first){
        sb.append("\n");
    }
    sb.append("}");
    System.out.println(sb.toString());

} else{
    System.out.println(myObject);
}

Output:

输出:

{
    'a':'1.0'
}

#4


2  

When Jackson is told to bind JSON into Object.class, it does just that; but since it has no a priori knowledge of what might be in that JSON (or what classes one might want to use), it has to use most basic Java types: Maps, Lists, Numbers, Booleans and Strings. So any JSON Object is represented by Map; JSON Array by List, and so on.

当Jackson被告知将JSON绑定到Object.class时,它就是这样做的;但由于它没有关于JSON中可能存在的内容(或者可能想要使用的类)的先验知识,因此它必须使用大多数基本Java类型:地图,列表,数字,布尔值和字符串。所以任何JSON对象都由Map表示;按列表的JSON数组,依此类推。

If you want a custom object, you must specify its type; or, when serializing, enable inclusion of explicit type information ("polymorphic type handling"). This will add either class name, or type name, and can be used to deserialize back to exact type.

如果需要自定义对象,则必须指定其类型;或者,在序列化时,启用包含显式类型信息(“多态类型处理”)。这将添加类名或类型名称,并可用于反序列化回确切类型。

To do this, either type itself (or one of its supertypes) must use @JsonTypeInfo annotation; or, if it is an Object property, @JsonTypeInfo for property (field or method).

要做到这一点,要么自己(或其中一个超类型)必须使用@JsonTypeInfo注释;或者,如果它是Object属性,则为@JsonTypeInfo属性(字段或方法)。

#1


7  

The created object will be a map (like the other comments) and so its toString produces what you're seeing, {a = 1}. To get your code to print something closer to your input value, you need to use Jackson to write it back out with something like:

创建的对象将是一个地图(就像其他注释一样),因此它的toString会产生您所看到的内容,{a = 1}。要让代码打印出更接近输入值的代码,您需要使用Jackson将其写回来,例如:

System.out.println(mapper.writeValueAsString(myObject));

That gives me what I believe you're looking for:

这给了我相信你正在寻找的东西:

{"a":1.0}

In other words, Jackson has deserialized your input string into an arbitrary Java object. When you call toString on the object, its own toString is, of course, used. This can write the object however it pleases, including using the method from Object. To reproduce the input string, you have to use Jackson to serialize our object back out.

换句话说,Jackson已将您的输入字符串反序列化为任意Java对象。当你在对象上调用toString时,当然会使用它自己的toString。这可以写它喜欢的对象,包括使用Object中的方法。要重现输入字符串,您必须使用Jackson将我们的对象序列化。

#2


3  

You need an existing class that matches the desired json structure. Object is not such class. You can still refer to it as Object, if that's needed:

您需要一个与所需json结构匹配的现有类。对象不是这样的类。如果需要,您仍然可以将其称为Object:

Object myObject = mapper.readValue("{\"a\": 1.0}", SomeClass.class);

#3


2  

If you use a debugger, you will see that the type of the returned Object is LinkedHashMap. So what you see is the output of LinkedHashMap.toString(). There's no way for Jackson to change that, so you can either cast it to a Map and create the String yourself or ask for another return type that generates the JSON String for you:

如果使用调试器,您将看到返回的Object的类型是LinkedHashMap。所以你看到的是LinkedHashMap.toString()的输出。杰克逊没有办法改变它,所以你可以将它转换为Map并自己创建String或者请求另一个为你生成JSON字符串的返回类型:

if(myObject instanceof Map<?, ?>){
    final Map<?, ?> map = (Map<?, ?>) myObject;
    final StringBuilder sb = new StringBuilder("{");
    boolean first = true;
    for(final Entry<?, ?> entry : map.entrySet()){
        if(first){
            first = false;
        } else{
            sb.append(",");
        }
        sb.append("\n\t'")
            .append(entry.getKey())
            .append("':'")
            .append(entry.getValue())
            .append("'");
    }
    if(!first){
        sb.append("\n");
    }
    sb.append("}");
    System.out.println(sb.toString());

} else{
    System.out.println(myObject);
}

Output:

输出:

{
    'a':'1.0'
}

#4


2  

When Jackson is told to bind JSON into Object.class, it does just that; but since it has no a priori knowledge of what might be in that JSON (or what classes one might want to use), it has to use most basic Java types: Maps, Lists, Numbers, Booleans and Strings. So any JSON Object is represented by Map; JSON Array by List, and so on.

当Jackson被告知将JSON绑定到Object.class时,它就是这样做的;但由于它没有关于JSON中可能存在的内容(或者可能想要使用的类)的先验知识,因此它必须使用大多数基本Java类型:地图,列表,数字,布尔值和字符串。所以任何JSON对象都由Map表示;按列表的JSON数组,依此类推。

If you want a custom object, you must specify its type; or, when serializing, enable inclusion of explicit type information ("polymorphic type handling"). This will add either class name, or type name, and can be used to deserialize back to exact type.

如果需要自定义对象,则必须指定其类型;或者,在序列化时,启用包含显式类型信息(“多态类型处理”)。这将添加类名或类型名称,并可用于反序列化回确切类型。

To do this, either type itself (or one of its supertypes) must use @JsonTypeInfo annotation; or, if it is an Object property, @JsonTypeInfo for property (field or method).

要做到这一点,要么自己(或其中一个超类型)必须使用@JsonTypeInfo注释;或者,如果它是Object属性,则为@JsonTypeInfo属性(字段或方法)。