本文介绍了我如何从json恢复对象映射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我有这堂课

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来正确地将对象序列化为地图的值,还是应该使用其他东西?

Can I make json to properly serialize objects as the values of the map or should I use something else?

已编辑

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泛型相关的问题.总而言之,当将数据反序列化为不可修改的类型(即在运行时无法获得实际类型信息的类型)时,您需要使用超类型令牌.通过阅读以下SO帖子,您可以了解有关什么是超类型令牌(以及为什么需要使用一个超令牌)的更多详细信息:

You are running into a problem related to Java generics. To summarize, when deserializing data into a non-reifiable type (aka a type for which actual type information is not available at runtime) you need to use a supertype token. You can get more detail about what a supertype token is (and why you need to use one) by reading these SO posts:

  • Pass parameterized type to method as argument
  • Error using Jackson and JSON
  • Deserialize JSON to ArrayList using Jackson

还有杰克逊(Jackson)文档中的信息:

And also from the Jackson documentation:

  • Data Binding With Generics
  • TypeReference Javadoc

基本问题是,当您使用典型的通用对象时,该对象的实际类型参数在运行时不可用.因此,杰克逊不知道要实例化哪个实际类并将数据反序列化到.

解决该问题的最简单方法是在JSON实用程序类中添加一个重载,该重载接受类型引用(与Class<T>相对).例如:

The easiest way to get around the problem would be adding an overload to your JSON utility class, that accepts a type reference (as opposed to a Class<T>). For example:

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>>(){});

这篇关于我如何从json恢复对象映射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 02:57