gpt4 book ai didi

java - 是否有一种通用的方法来反序列化 Jackson 中的单值对象(没有自定义反序列化器)

转载 作者:塔克拉玛干 更新时间:2023-11-01 23:00:07 26 4
gpt4 key购买 nike

我们使用很多具有单个值的值对象。对于(反)序列化,我们使用 Jackson 和 kotlin 模块。

Kotlin 中的示例值对象:

data class MyValueObject(val value: String)

或作为Java

class MyValueObject {
private String value;

public MyValueObject(String value) { this.value = value; }

public String getValue() { return value; }
}

这些值对象必须被序列化和反序列化并且应该被序列化为“仅值”,例如。 "theValue" 而不是 "{"value":"theValue"}"

我想避免为许多值对象编写自定义序列化器/反序列化器。

我知道序列化@JsonValue可以用来实现上面的。

data class MyValueObject(@JsonValue val value: String)

但是 JSON ""theValue""(上面序列化的 String-Literal)不能反序列化回 MyValueObject。它导致以下异常:

com.fasterxml.jackson.databind.exc.MismatchedInputException: 
Cannot construct instance of `[...].MyValueObject` (although at least one Creator exists):
no String-argument constructor/factory method to deserialize from String value ('test')
at [Source: (String)""test""; line: 1, column: 1]

这是我使用的单元测试:

@Test
fun testSerialize() {
val objectMapper = ObjectMapper()
.registerModule(Jdk8Module())
.registerModule(KotlinModule())
val test = MyValueObject("test")
val json = objectMapper.writeValueAsString(test)
println(json)
objectMapper.readValue<MyValueObject>(json)
}

是否有一种简单/通用的方法来反序列化这些序列化,例如 @JsonValue 以进行序列化?

P.S.:一个可行的解决方案(感谢@LppEdd)是:

data class MyValueObject (@JsonValue val value: String) {

companion object {
@JvmStatic
@JsonCreator
fun create(value: String) = MyValueObject(value)
}
}

但这非常冗长。在构造函数上注释的@JsonCreator 对我不起作用(请参阅我对@LppEdd 的回答的评论)

最佳答案

当然可以,而且非常简单。
只需将 @JsonCreator 添加到构造函数即可。

class MyValueObject {
private String value;

@JsonCreator
public MyValueObject(String value) { this.value = value; }

@JsonValue
public String getValue() { return value; }
}

或者对于 Kotlin,我想你会拥有

data class MyValueObject @JsonCreator constructor(@JsonValue val value: String)

当你使用@JsonCreator没有给构造函数参数加上前缀

@JsonProperty("fieldName")

您告诉 Jackson 传递整个 JSON 字符串,在您的情况下这只是一个“原始”值。


显然 Kotlin 不喜欢自动生成的 getter/setter 对。
这例如有效

class MyValueObject @JsonCreator constructor(private val value: String) {
@JsonValue
fun getValue() = value
}

另外调试了一下,发现问题出在这里

@Override
public Boolean hasAsValue(Annotated a) {
JsonValue ann = _findAnnotation(a, JsonValue.class);
if (ann == null) {
return null;
}
return ann.value();
}

JacksonAnnotationIntrospector 处。

我不知道为什么,但 Jackson 仍然在 public 字段或 public getter 上寻找 @JsonValue 注释。 Kotlin 将注释放在 private 字段中,因此 Jackson 无法找到它。

解决办法是

data class MyValueObject @JsonCreator constructor(@JvmField @JsonValue val value: String)

甚至更好

data class MyValueObject @JsonCreator constructor(@get:JsonValue val value: String)

正如 Marc von Renteln 在评论中所写,您也可以省略 @JsonCreator

data class MyValueObject(@get:JsonValue val value: String)

然而,这似乎没有记录。如果有人能指出描述此行为的位置,那就太棒了!

关于java - 是否有一种通用的方法来反序列化 Jackson 中的单值对象(没有自定义反序列化器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55492657/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com