我有这门课
public static class SomeClass {
public SomeClass(String field) {
this.field = field;
}
private final String field;
public String getField() {
return field;
}
}
我也有这个测试(编辑)
@Test
public void testStringifyMapOfObjects() {
Map<String, SomeClass> original = Maps.newTreeMap();
original.put("first", new SomeClass("a"));
original.put("second", new SomeClass("b"));
String encoded = JsonUtil.toJson(original);
Map<String, SomeClass> actual = JsonUtil.fromJson(encoded, Map.class);
Assert.assertEquals("{'first':{'field':'a'},'second':{'field':'b'}}", encoded.replaceAll("\\s", "").replaceAll("\"", "'"));
Assert.assertEquals(original.get("first"), actual.get("first"));
}
测试失败并显示
junit.framework.AssertionFailedError: expected:<eu.ec.dgempl.eessi.facade.transport.test.TestToolTest$SomeClass@6e3ed98c> but was:<{field=a}>
at junit.framework.Assert.fail(Assert.java:47)
at junit.framework.Assert.failNotEquals(Assert.java:277)
at junit.framework.Assert.assertEquals(Assert.java:64)
at junit.framework.Assert.assertEquals(Assert.java:71)
at eu.ec.dgempl.eessi.facade.transport.test.TestToolTest.testStringifyMapOfObjects(TestToolTest.java:90)
我可以制作 json 来正确序列化对象作为 map 的值还是应该使用其他东西?
已编辑
public class JsonUtil {
private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(JsonUtil.class);
public static <T> String toJson(T data) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(Feature.INDENT_OUTPUT, true);
try {
return mapper.writeValueAsString(data);
} catch (IOException e) {
LOG.warn("can't format a json object from [" + data + "]", e);
return null;
}
//
// return Json.stringify(Json.toJson(data));
}
public static <T> T fromJson(String description, Class<T> theClass) {
try {
JsonNode parse = new ObjectMapper().readValue(description, JsonNode.class);
T fromJson = new ObjectMapper().treeToValue(parse, theClass);
return fromJson;
} catch (JsonParseException e) {
// throw new RuntimeException("can't parse a json object of type " + theClass.getName() + " from [" + description + "]", e);
LOG.warn("can't parse a json object from [" + description + "]", e);
return null;
} catch (JsonMappingException e) {
// throw new RuntimeException("can't parse a json object of type " + theClass.getName() + " from [" + description + "]", e);
LOG.warn("can't parse a json object from [" + description + "]", e);
return null;
} catch (IOException e) {
// throw new RuntimeException("can't parse a json object of type " + theClass.getName() + " from [" + description + "]", e);
LOG.warn("can't parse a json object from [" + description + "]", e);
return null;
}
}
}
最佳答案
您遇到了与 Java 泛型相关的问题。总而言之,当将数据反序列化为不可具体化类型(也称为运行时实际类型信息不可用的类型)时,您需要使用父类(super class)型标记。您可以通过阅读以下 SO 帖子来详细了解什么是父类(super class)型标记(以及为什么需要使用父类(super class)型标记):
- Pass parameterized type to method as argument
- Error using Jackson and JSON
- Deserialize JSON to ArrayList using Jackson
也来自 Jackson 文档:
基本问题是,当您使用典型的泛型对象时,该对象的实际类型参数在运行时不可用。因此 Jackson 不知道将数据实例化和反序列化到哪个实际类。
解决该问题的最简单方法是向 JSON 实用程序类添加一个重载,该类接受类型引用(而不是 Class<T>
)。例如:
public static <T> T fromJson(String json, TypeReference<T> typeRef) {
if(json == null || typeRef == null) return null;
return new ObjectMapper().readValue(json, typeRef);
}
这样使用:
Map<String, SomeClass> actual = JsonUtil.fromJson(
encoded,
new TypeReference<Map<String, SomeClass>>(){});
关于java - 我如何从 json 恢复对象映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16609266/