在 Kotlin 中,为什么 Jackson 在某些情况下无法解组未注释的对象而在其他情况下却失败
In Kotlin, why Jackson fails unmarshalling non-annotated object in some cases and not in others
我正在使用 Kotlin 和 Jongo 来访问 MongoDB。 Jongo 使用 Jackson 来 serialize/deserialize 对象,以便从 MongoDB 中保存和读取它们。我使用 Jackson-Kotlin 模块来帮助使用构造函数序列化 Kotlin 数据 classes。
这是一个数据class 的示例,它可以很好地序列化:
data class Workflow (
@field:[MongoId MongoObjectId] @param:MongoId
var id: String? = null,
val name: String,
val states: Map<String, State>
)
这是一个无法反序列化的类似 class 的示例:
data class Session (
@field:[MongoObjectId MongoId] @param:MongoId
var id: String? = null,
var status: CallStatus,
var currentState: String,
var context: MutableMap<String, Any?>,
val events: MutableMap<String, Event>
)
由于 Jackson 反序列化失败,Jongo 抛出以下异常:
org.jongo.marshall.MarshallingException: Unable to unmarshall result to class example.model.Session from content { "_id" : { "$oid" : "56c4976aceb2503bf3cd92c2"} , "status" : "Ongoing" , "currentState" : "Start" , "context" : { } , "events" : { }}
... bunch of stack trace entries ...
Caused by: java.lang.IllegalArgumentException: Argument #1 of constructor [constructor for example.model.Session, annotations: [null]] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
如果我像这样完全注释会话数据 class,它确实有效:
data class Session (
@field:[MongoObjectId MongoId] @param:MongoId
var id: String? = null,
@JsonProperty("status")
var status: CallStatus,
@JsonProperty("currentState")
var currentState: String,
@JsonProperty("context")
var context: MutableMap<String, Any?>,
@JsonProperty("events")
val events: MutableMap<String, Event>
}
我的问题是,为什么它适用于 Workflow?当会话数据 class 未完全注释时,导致解组失败的细微差别是什么?
编辑
不同之处在于我从 Gradle 测试了 Workflow 测试用例 运行,它使用了不同版本的 Kotlin 然后是我 运行 来自 IDE 的 Session 测试用例]A IDE。 IDEA 的 Kotlin 插件更新也更新了 IDEA 用于 运行 测试用例的 Kotlin 版本,我没有注意到。这导致 Kotlin 和 Jackson-Kotlin 库的版本不匹配。下面接受的答案指出了需要配置什么才能让事情重新开始。
如果 MongoDB 使用的 ObjectMapper
没有注册 Jackson-Kotlin 模块,您会收到此错误。您的 JsonProperty
注释基本上与模块隐式执行的操作相同。但如果它不存在,您将收到相同的错误消息。
要看的东西:
您的 Jackson-Kotlin 模块兼容版本与您的 Kotlin 代码版本相匹配。对于 RC 1050 或更新版本,您需要 README.MD file on GitHub 中提到的 Jackson 模块的最新版本。
Older versions of the Jackson-Kotlin module are not compatible with Kotlin 1.0.0. You must update or you will have silent failures (the module cannot recognize a Kotlin class, so ignores it). Releases for Kotlin 1.0.0 will be available on Maven Central shortly. In the meantime use the EAP repository:
maven {
url "http://dl.bintray.com/jaysonminard/kohesive"
}
For Kotlin 1.0.0, use one of:
- release
2.7.1-1
(for Jackson 2.7.x
)
- release
2.6.5-2
(for Jackson 2.6.x
)
- release
2.5.5-2
(for Jackson 2.5.x
)
Later this will move back to Maven Central.
发送给杰克逊的实际 JSON 是多少
- 此错误是来自堆栈跟踪中的 MongoDB,还是 Jackson 确实参与其中(它是否在调用 Jackson 之前预处理并确定错误)?
- MongoDB 如何获得它的 ObjectMapper 以及您是如何尝试配置它的?
我正在使用 Kotlin 和 Jongo 来访问 MongoDB。 Jongo 使用 Jackson 来 serialize/deserialize 对象,以便从 MongoDB 中保存和读取它们。我使用 Jackson-Kotlin 模块来帮助使用构造函数序列化 Kotlin 数据 classes。
这是一个数据class 的示例,它可以很好地序列化:
data class Workflow (
@field:[MongoId MongoObjectId] @param:MongoId
var id: String? = null,
val name: String,
val states: Map<String, State>
)
这是一个无法反序列化的类似 class 的示例:
data class Session (
@field:[MongoObjectId MongoId] @param:MongoId
var id: String? = null,
var status: CallStatus,
var currentState: String,
var context: MutableMap<String, Any?>,
val events: MutableMap<String, Event>
)
由于 Jackson 反序列化失败,Jongo 抛出以下异常:
org.jongo.marshall.MarshallingException: Unable to unmarshall result to class example.model.Session from content { "_id" : { "$oid" : "56c4976aceb2503bf3cd92c2"} , "status" : "Ongoing" , "currentState" : "Start" , "context" : { } , "events" : { }}
... bunch of stack trace entries ...
Caused by: java.lang.IllegalArgumentException: Argument #1 of constructor [constructor for example.model.Session, annotations: [null]] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
如果我像这样完全注释会话数据 class,它确实有效:
data class Session (
@field:[MongoObjectId MongoId] @param:MongoId
var id: String? = null,
@JsonProperty("status")
var status: CallStatus,
@JsonProperty("currentState")
var currentState: String,
@JsonProperty("context")
var context: MutableMap<String, Any?>,
@JsonProperty("events")
val events: MutableMap<String, Event>
}
我的问题是,为什么它适用于 Workflow?当会话数据 class 未完全注释时,导致解组失败的细微差别是什么?
编辑
不同之处在于我从 Gradle 测试了 Workflow 测试用例 运行,它使用了不同版本的 Kotlin 然后是我 运行 来自 IDE 的 Session 测试用例]A IDE。 IDEA 的 Kotlin 插件更新也更新了 IDEA 用于 运行 测试用例的 Kotlin 版本,我没有注意到。这导致 Kotlin 和 Jackson-Kotlin 库的版本不匹配。下面接受的答案指出了需要配置什么才能让事情重新开始。
如果 MongoDB 使用的 ObjectMapper
没有注册 Jackson-Kotlin 模块,您会收到此错误。您的 JsonProperty
注释基本上与模块隐式执行的操作相同。但如果它不存在,您将收到相同的错误消息。
要看的东西:
您的 Jackson-Kotlin 模块兼容版本与您的 Kotlin 代码版本相匹配。对于 RC 1050 或更新版本,您需要 README.MD file on GitHub 中提到的 Jackson 模块的最新版本。
Older versions of the Jackson-Kotlin module are not compatible with Kotlin 1.0.0. You must update or you will have silent failures (the module cannot recognize a Kotlin class, so ignores it). Releases for Kotlin 1.0.0 will be available on Maven Central shortly. In the meantime use the EAP repository:
maven { url "http://dl.bintray.com/jaysonminard/kohesive" }
For Kotlin 1.0.0, use one of:
- release
2.7.1-1
(for Jackson2.7.x
) - release
2.6.5-2
(for Jackson2.6.x
) - release
2.5.5-2
(for Jackson2.5.x
)
Later this will move back to Maven Central.
- release
发送给杰克逊的实际 JSON 是多少
- 此错误是来自堆栈跟踪中的 MongoDB,还是 Jackson 确实参与其中(它是否在调用 Jackson 之前预处理并确定错误)?
- MongoDB 如何获得它的 ObjectMapper 以及您是如何尝试配置它的?