Jackson:使用@JsonUnwrapped注解反序列化Java记录时“无法设置final”

jgzswidk  于 2023-01-07  发布在  Java
关注(0)|答案(1)|浏览(180)

我有一个简单的Java记录,其中Address类使用传统的POJO。序列化按预期工作,但反序列化失败,并显示错误消息"Cannotsetfinal"

public record TestRecord(String name, @JsonUnwrapped Address address) {}

序列化这个工作正常。

Address address = new Address();
address.setCity("New York");
address.setState("NY");
TestRecord rec = new TestRecord("Bob", address);

JsonMapper jsonMapper = new JsonMapper();
jsonMapper.writeValueAsString(rec); // {"name":"Bob","city":"New York","state":"NY"}

但是反序列化会抛出一个异常:

@Test
void should_DeserializeUnwrappedRecord() throws JsonProcessingException {

    Address address = new Address();
    address.setCity("New York");
    address.setState("NY");
    TestRecord expectedRecord = new TestRecord("Bob", address);

    String json = """
            {"name":"Bob","city":"New York","state":"NY"}""";

    JsonMapper jsonMapper = new JsonMapper();
    TestRecord actualValue = jsonMapper.readValue(json, TestRecord.class);
    assertEquals(expectedRecord, actualValue);
}

例外情况:

com.fasterxml.jackson.databind.JsonMappingException: Can not set final org.example.AppTest$Address field org.example.AppTest$TestRecord.address to org.example.AppTest$Address
 at [Source: UNKNOWN; byte offset: #UNKNOWN]

    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:276)
Caused by: java.lang.IllegalAccessException: Can not set final org.example.AppTest$Address field org.example.AppTest$TestRecord.address to org.example.AppTest$Address
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)
    at java.base/jdk.internal.reflect.UnsafeQualifiedObjectFieldAccessorImpl.set(UnsafeQualifiedObjectFieldAccessorImpl.java:79)
    at java.base/java.lang.reflect.Field.set(Field.java:799)

如果我将TestRecord更改为一个普通的Java类,它可以正常工作。

nuypyhwy

nuypyhwy1#

TestRecord是一个记录,这意味着它的所有字段都是final。因此,您可以使用默认配置将JSON反序列化到此对象。
我认为你有两个选择:
1.使用JsonProperty标记每个字段

public record TestRecord(@JsonProperty("name") String name, @JsonUnwrapped Address address) {}
 public record Address(@JsonProperty("city") String city, @JsonProperty("state") String state) {}

1.使用以下项更改Jackson的字段可见性级别:

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public record TestRecord(String name, @JsonUnwrapped Address address) {}

相关问题