将JSON字符串转换为“Object.class”

时间:2012-07-10 17:31:55

标签: java json serialization jackson

我目前正在尝试使用Jackson将对象转换为JSON字符串,这很容易通过

完成
public byte[] toJSON(Object obj) throws IOException {
        ObjectMapper map = new ObjectMapper();
        return map.writeValueAsString(obj).getBytes();
    }

我遇到麻烦的时候是我要把字节数组转换成一个对象。目前我有:

public Object toObject(byte[] bytes) throws IOException, ClassNotFoundException {
    ObjectMapper map = new ObjectMapper();
    return (Object)map.readValue(bytes, Object.class);
}

我成功将对象转换为JSON字符串,但是从toObject方法返回的Object始终是LinkedHashMap,而不是最初转换为JSON字符串的对象。

很抱歉,如果我在沟通我的问题方面表现不佳,但是我只是试着总结一下。我希望我的代码能够执行以下操作:

MyClass someObject = new MyClass();
String json = toJSON(someObject);
Object tempObject = toObject(json);
MyClass sameObject = (MyClass) tempObject;

此代码目前引发以下内容:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.MyClass

对此事的任何帮助都将不胜感激!

2 个答案:

答案 0 :(得分:1)

您正在申请Object,因此杰克逊创建了一个Object,知道它可以创建:Map。 JSON数组将成为List,依此类推。

如果你想要MyClass,你必须明确地请求它,或者,如果你想要一个通用的序列化/反序列化,要包含类型标识符,如@csd所建议的那样。

答案 1 :(得分:0)

首先,我有点困惑为什么你需要处理byte[]objectMapper.writeVaueAsString(obj)为您提供了一个非常好的String,其中包含您对象的JSON表示。如果您需要转换为byte[],则需要在致电String之前转换回readValue

但暂时把它放在一边,让我们假设你已经得到了包含JSON的String。默认情况下,杰克逊不够聪明(仅通过查看JSON)知道在调用readValue时要实例化的Java类。在您的示例中,您传入了Object.class,这对Jackson来说并不是很有用,因为Java中的每个对象都来自Object。因此,在这种情况下,它会选择其内置默认值,即使用JSON中列出的键和值构建Map(特别是LinkedHashMap)。

正如一位评论者指出的那样,你可以给杰克逊一个提示并将MyClass.class作为第二个参数传递给readValue(而不是Object.class)。如果您这样做,那么JSON将在MyClass的开头创建readValue的实例。当它在JSON中看到类似“foo: 43”的内容时,它会尝试在public int foo;中找到字段或setter(即public void setFoo(int f)MyClass)并设置相应的价值。

如果您事先不知道它是什么类型的对象(即作为第二个参数传递给readValue的值),那么还有其他选项。其中一个示例是要求您的JSON对象具有class属性,Jackson将使用该属性作为要创建的Java对象类型的提示。这是代码的样子:

// This annotation tells Jackson to include the class name as
// a "class" property when *writing* JSON.
@JsonTypeInfo(include=As.PROPERTY, use=Id.CLASS, property="class")
public class MyClass {
    public int foo;
}

这将使您的JSON看起来像这样:

{ "class":"MyClass", foo:0 }

然后在你的代码中读取对象,执行以下操作:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enableDefaultTypingAsProperty(DefaultTyping.JAVA_LANG_OBJECT, "class");
// Note Object.class as second parameter.  Jackson will find the "class"
// property in the JSON and use it to determine which class to make.
MyClass foo = (MyClass) objectMapper.readValue(jsonString, Object.class);