【问题标题】:POJO object for this XML response in kotlinkotlin 中此 XML 响应的 POJO 对象
【发布时间】:2018-04-17 18:39:21
【问题描述】:

我正在使用一个返回 XML 的 API:

<xyz-objects version="1.0">
    <object pk="1" model="roll">
        <field type="BigIntegerField" name="roll_number">1000000714</field>
        <field type="CharField" name="status">DL</field>
        <field name="scans">
            <object pk="1" model="scan_stages">
                <field type="DateTimeField" name="updated_on">11 Jul, 2017, 17:40</field>
            </object>
        </field>        
    </object>
</xyz-objects>

我正在使用 Jackson 的 XML 映射器。

我尝试为此编写一个 POJO 对象,但这不起作用。

如何处理类型和名称等元素的属性? 可以举例吗?

【问题讨论】:

  • “我试着写...” - 好!您的代码的相关部分?有什么错误(究竟是什么错误)?
  • 首先:您的 XML 无效 :) xyz-objectsecomexpress-objects 关闭。此外,您还缺少&lt;/field&gt;scans。明显是错别字。
  • @madhead 已经完成了..现在请回答

标签: java xml jackson kotlin


【解决方案1】:

根据我在https://github.com/FasterXML/jackson-module-kotlin/issues/138 中所做的调查,这是一个比JsonNode workaround by madhead 输入更多的解决方法

data class Field(
    @JacksonXmlProperty(isAttribute = true)
    val type: String,

    @JacksonXmlProperty(isAttribute = true)
    val name: String,
) {
    @JacksonXmlText
    lateinit var value: String private set
}

【讨论】:

    【解决方案2】:

    由于您没有提供架构,因此很难猜测模型的某些部分。特别是,很难猜出field 模型。所以我将把它反序列化成一个JsonNode,一个可以处理几乎所有事情的动态对象。 JsonIgnoreProperties 以防万一你有一些额外的字段,这里没有提到。

    首先,创建一些数据类:

    @XmlRootElement(name = "xyz-objects")
    @JsonIgnoreProperties(ignoreUnknown = true)
    data class XyzObjects(
            @JacksonXmlProperty(isAttribute = true)
            val version: String,
    
            @JsonProperty(value = "object")
            @JacksonXmlElementWrapper(useWrapping = false)
            val objects: List<Object>
    )
    
    @XmlRootElement(name = "object")
    @JsonIgnoreProperties(ignoreUnknown = true)
    data class Object(
            @JacksonXmlProperty(isAttribute = true)
            val pk: String,
    
            @JacksonXmlProperty(isAttribute = true)
            val model: String,
    
            @JsonProperty(value = "field")
            @JacksonXmlElementWrapper(useWrapping = false)
            val fields: List<JsonNode>
    )
    

    回答您的问题:您可以使用JacksonXmlPropertyisAttribute 属性来处理属性。列表可以用JacksonXmlElementWrapper + JsonProperty 处理(不要被名称所迷惑,它用于处理名称中的复数,从而使它们在 XML 中也更易于阅读)。

    为了能够使用数据类,您需要将Kotlin module 注册到registerKotlinModule

    val text = """<xyz-objects version="1.0">
    <object pk="1" model="roll">
        <field type="BigIntegerField" name="roll_number">1000000714</field>
        <field type="CharField" name="status">DL</field>
        <field name="scans">
            <object pk="1" model="scan_stages">
                <field type="DateTimeField" name="updated_on">11 Jul, 2017, 17:40</field>
            </object>
        </field>
    </object>
    </xyz-objects>"""
    val mapper = XmlMapper().registerKotlinModule()
    val node = mapper.readValue<XyzObjects>(text)
    
    println(node)
    

    它将打印:

    XyzObjects(version=1.0, objects=[Object(pk=1, model=roll, fields=[{"type":"BigIntegerField","name":"roll_number","":"1000000714"}, {"type":"CharField","name":"status","":"DL"}, {"name":"scans","object":{"pk":"1","model":"scan_stages","field":{"type":"DateTimeField","name":"updated_on","":"11 Jul, 2017, 17:40"}}}])])
    

    【讨论】:

    • 这将返回“参数 #0 没有属性名称注释;当多参数构造函数注释为 Creator 时必须具有名称”然后我将 localName 属性添加到元素,然后它返回:“参数指定为非null 为 null:参数 pk"
    • 这只是一个例子。在不知道您的完整架构的情况下,我无法预测确切的类型。在这里,请参阅:“指定为非空的参数为空:参数 pk”我没想到 pk 在某些情况下为空,因为您的所有示例都有它。对于这种特殊情况,请使用可为空的类型:val pk: String?
    • 我在这个问题中使用了相同的 XML
    • 不,你没有。在那个 XML all Object 有非空的 pk
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 2018-04-21
    • 1970-01-01
    • 2017-09-05
    相关资源
    最近更新 更多