将 Json 字符串解析为 Kotlin 对象会与 Jackson 一起引发 InvalidDefinitionException

Posted

技术标签:

【中文标题】将 Json 字符串解析为 Kotlin 对象会与 Jackson 一起引发 InvalidDefinitionException【英文标题】:Parse Json String into Kotlin Object throws InvalidDefinitionException with Jackson 【发布时间】:2019-01-25 17:06:22 【问题描述】:

我从 API 获得了一个 Json 字符串,并希望将其解析为 Kotlin 对象。

我的 Json:


  "Title": "The Secret Life of Walter Mitty",
  "Year": "2013",
  "Rated": "PG",
  "Released": "25 Dec 2013",
  "Runtime": "114 min",
  "Genre": "Adventure, Comedy, Drama",
  "Director": "Ben Stiller",
  "Writer": "Steve Conrad (screenplay by), Steve Conrad (screen story by), James Thurber (based on the short story by)",
  "Actors": "Ben Stiller, Kristen Wiig, Jon Daly, Kathryn Hahn",
  "Language": "English, Spanish, Icelandic",
  "Country": "USA, UK",
  "Awards": "5 wins & 18 nominations.",
  "Poster": "https://m.media-amazon.com/images/M/MV5BODYwNDYxNDk1Nl5BMl5BanBnXkFtZTgwOTAwMTk2MDE@._V1_SX300.jpg",
  "Ratings": [
    
      "Source": "Internet Movie Database",
      "Value": "7.3/10"
    ,
    
      "Source": "Rotten Tomatoes",
      "Value": "51%"
    ,
    
      "Source": "Metacritic",
      "Value": "54/100"
    
  ],
  "Metascore": "54",
  "imdbRating": "7.3",
  "imdbVotes": "265,701",
  "imdbID": "tt0359950",
  "Type": "movie",
  "DVD": "15 Apr 2014",
  "BoxOffice": "$'$'33,223,430",
  "Production": "20th Century Fox",
  "Website": "http://WalterMitty.com",
  "Response": "True"

我的 Kotlin 电影对象:

@JsonIgnoreProperties(ignoreUnknown = true)
data class Movie(

    var id: Long?,

    @JsonProperty("Title")
    var title: String,

    @JsonProperty("Released")
    var release: String,

    @JsonProperty("Runtime")
    var runtime: String,

    @JsonProperty("Genre")
    var genre: String,

    @JsonProperty("Director")
    var director: String,

    @JsonProperty("Actors")
    var actor: String,

    @JsonProperty("Plot")
    var description: String,

    @JsonProperty("Poster")
    var posterLink: String?,

    @JsonProperty("Metascore")
    var metaScoreRating: String
)

我将 Json 解析为电影对象的片段:

...
    var mapper = ObjectMapper()
    mapper.readValue(jsonFromAPI, Movie::class.java)
...

但是当我运行这段代码时,我得到了这个异常:

InvalidDefinitionException: Invalid type definition for type `model.Movie`: Argument #0 of constructor [constructor for model.Movie, annotations: [null]] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator

但我不知道为什么.. Kotlin 数据类构建每个构造函数,所以我不必声明特定的构造函数.. 我猜 Id 有一些东西。

【问题讨论】:

因为构造函数的第一个参数 (Argument #0 of constructor) 没有 @JsonProperty 指定该参数的 JSON 属性名称 (has no property name annotation) 但是 Json 不包含 Id。此对象中的 Id 是我的数据库中的主键。 【参考方案1】:

我认为您需要确保注册 jackson kotlin module,例如添加对数据类的支持。

增加对 Kotlin 序列化/反序列化支持的模块 类和数据类。以前默认构造函数必须有 存在于 Kotlin 对象上供 Jackson 反序列化为 目的。有了这个模块,可以使用单个构造函数类 自动,以及具有辅助构造函数或静态的那些 也支持工厂。

这样您就可以创建一个ObjectMapper,该模块已经使用com.fasterxml.jackson.module.kotlin.ExtensionsKt#jacksonObjectMapper 注册了该模块。 (请注意如何使用它提供的扩展之一来避免声明有效负载类)

var mapper = jacksonObjectMapper()
val movie: Movie = mapper.readValue(payload)

作为替代方案,您仍然可以创建对象映射器并使用常用 API 注册模块:

var mapper = ObjectMapper()
mapper.registerModule(KotlinModule())

【讨论】:

嘿谢谢!!我从没想过:D 两种解决方案都适合我【参考方案2】:

只需将@JsonIgnore 注释添加到您的var id: Long? 属性

【讨论】:

我试过了,但@JsonIgnoreProperties(ignoreUnknown = true) 也一样,它仍然抛出异常.. 尝试为id 添加默认值,例如var id: Long? = null

以上是关于将 Json 字符串解析为 Kotlin 对象会与 Jackson 一起引发 InvalidDefinitionException的主要内容,如果未能解决你的问题,请参考以下文章

如何通过改造将数组嵌套对象 Json 解析为 Kotlin?

Kotlin 使用 Gson 将 json 字符串转换为对象列表

如何在 Android 的 Kotlin 中使用 GSON 将 JSON 对象转换为 JSON 数组

Kotlin入门(31)JSON字符串的解析

尝试解析 json 字符串,但得到对象“”的预期开始,但改为“EOF”

如何使用 Kotlin 序列化解析 JSON 对象列表中的第一个属性?