当前位置: 首页 > 知识库问答 >
问题:

使Jackson反序列化为没有setter或constructor的私有字段

乜清野
2023-03-14

我成功地将Jackson配置为序列化一个类,而不在类内部的私有字段上使用任何getter或注释

objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

但我无法使这个非静态类的JSON字符串反序列化为一个没有任何参数化构造函数或设置器的对象。这是不是可能的--我想应该通过思考,但我不知道具体是怎么...

这里有两个测试,需要通过,以达到我的需要:

public class ObjectMapperTest {

    private ObjectMapper mapper;

    @Before
    public void init() {
        mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
    }

    @Test
    public void serialize() throws Exception {
        Payload payloadToSerialize = new Payload();
        payloadToSerialize.data = "testData";
        String serializedPayload = mapper.writeValueAsString(payloadToSerialize);
        assertThat(serializedPayload, is("{\"data\":\"testData\"}"));
        // --> OK
    }

    @Test
    public void deserialize() throws Exception {
        Payload deserializedPayload = mapper.readValue("{\"data\":\"testData\"}", Payload.class);
        assertThat(deserializedPayload.data, is("testData"));
        // com.fasterxml.jackson.databind.JsonMappingException:
        // No suitable constructor found for type [simple type, class ...ObjectMapperTest$Payload]:
        // can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
        // at [Source: {"data":"testData"}; line: 1, column: 2]
    }

    public class Payload {

        private String data;

        public Payload() {
            // empty constructor for Jackson
        }
    }
}

共有1个答案

佟和安
2023-03-14

您可以编写自己的反序列化器来解析JSON并创建payload的实例,然后使用反射设置data值。示例:

@Before
public void init() {
    mapper = new ObjectMapper();
    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
    mapper.registerModule(
        new SimpleModule()
        .addDeserializer(Payload.class, new JsonDeserializer<Payload>() {
            @Override
            public Payload deserialize(JsonParser parser, DeserializationContext ctx)
                throws IOException, JsonProcessingException {
                JsonNode obj = parser.readValueAsTree(); // Read the JSON as a node

                Payload payload = new Payload();
                if (obj.isObject() && obj.has("data")) { // The node is an object and has a "data" field
                    try {
                        // Use reflection to set the value
                        Field dataField = payload.getClass().getDeclaredField("data");
                        dataField.setAccessible(true);
                        dataField.set(payload, obj.get("data").asText());
                    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
                        throw new IOException("Reflection error", ex);
                    }
                }
                return payload;
            }
        }));
}

编辑:如果您想要一些更“通用”的东西,您可以尝试自己创建实例并更改所有字段的可访问性。然后告诉Jackson使用JSON更新值。

public <T> T deserialize(final String json, final T instance) throws Exception {
    for (Field field : instance.getClass().getDeclaredFields()) {
        field.setAccessible(true);
    }
    mapper.readerForUpdating(instance).readValue(json);
    return instance;
}


@Test
public void deserializeUpdate() throws Exception {
    Payload deserializedPayload = deserialize("{\"data\":\"testData\"}", new Payload());
    assertThat(deserializedPayload.data, is("testData"));
}

我在你的有效负载类上测试了这个,也许它在更复杂的对象上不起作用。

 类似资料:
  • 问题内容: 使用包中的类时遇到了json解析问题,而我得到的错误是: 发生此问题的Web应用程序是使用AngularJS前端的Spring MVC应用程序,但是我可以使用更小的所有Java程序来复制该问题。这是我的豆子: Shipment.java Activity.java ActivityLocation.java Address.java 这是我可以正确映射json的代码: 调整中的数据时,

  • 我目前正在努力反序列化JSON数据结构,如下所示: 示例1: 示例 2: 我必须处理许多此类结构的实例。它是规则生成器的输出。我无法更改JSON的格式,我必须使用我得到的东西。该结构是递归的,可以有多个级别。 我正在使用Jackson的ObjectMapper并构建一些内部类来映射数据。 大多数实例看起来像示例1,对于那些已经很好地工作的实例,但是有一些更复杂的实例,比如示例2,实际上比示例2更复

  • 使用Jackson将JSON响应反序列化为DTO。 使用Gson或Jackson反序列化JSON时忽略空字段 他们仍然从那个不规则的JSON对象创建一个对象。 这意味着我需要遍历这个列表,并通过实现一个清理方法删除所有不具有属性“value”的对象。 我的带有Jackson注释的DTO: 给定JSON响应的结果是初始化了3个DTOs,而不是4个。

  • 我有一个基类,它使用php魔术方法__get和__set,可以修改扩展类中的私有属性。然后,我为相关的私有属性构建setter getter函数(类似于http://www.beaconfire-red.com/epic-stufle/better-getters-and-setters-php)

  • 我将JSON用于我的RESTful服务,并且我有JSON(作为有效负载载体格式)。 我在接口上使用。类实现。扩展 非常感谢任何帮助。

  • 可以反序列化到具有私有字段和自定义参数构造函数的类,而无需使用注释,也无需使用Jackson? 我知道在Jackson中使用这种组合是可能的:1)Java 8,2)使用“-parameters”选项编译,3)参数名称与JSON匹配。但在GSON中,默认情况下也可以不受所有这些限制。 例如: 这对GSON来说很好,但Jackson提出: 这在GSON中是可能的,所以我认为Jackson中一定有某种方