我目前正在尝试使用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
对此事的任何帮助都将不胜感激!
答案 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);