java - 我如何从 json 恢复对象映射?

标签 java json jsonserializer serialization

我有这门课

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)型标记):

也来自 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/

相关文章:

java - 日期格式转换在 Java 中未按预期工作

java - 如何使我在 MySQL 数据库中的主键适用于小写和大写?

.net - 周转基金。 REST 架构。如何在 JSON (POST) 中从客户端获取对象

ServiceStack JSON 类型定义应以 '{' 开头

Ruby 对象和 JSON 序列化(没有 Rails)

java - Spring Kafka-Consumer.poll() 到底什么时候在幕后被调用?

Javafx 2 TreeView - 隐藏根项目

html - Objective-c:如何在没有 UIWebView 的情况下在 iOS 中将 html <img> 标签显示为图像

json - 如何使用jq删除数组元素?

C# 无法从 API 调用读取 json 响应