我正在尝试从API解析XML响应,并且“字段”元素列表有问题。我正在尝试在元素内部创建属性和文本的Field对象,例如该对象的属性,并且找不到要用于元素文本的注释。我尝试使用
@get:Text
@set:Text
和
@field:Text
但有相同的错误
java.lang.RuntimeException: org.simpleframework.xml.core.PersistenceException: Constructor not matched for class NetworkTestContainer$Field
有人可以为此情况给我一个适当的注释吗?
具有XML结构:
<response>
<commands>
<command>
<nick>QUEUECAUSES_LIST</nick>
<result>
<DATASET Version="1.0" Class="TQueryAdv" Name="">
<Row Index="1">
<Field Name="SHOPID" Type="6" Size="0">-1</Field>
<Field Name="IDCODE" Type="6" Size="0">3000000000001</Field>
<Field Name="CAPTION" Type="1" Size="255">Консультация</Field>
<Field Name="PRIORITY" Type="6" Size="0">0</Field>
</Row>
<Row Index="2">
<Field Name="SHOPID" Type="6" Size="0">-1</Field>
<Field Name="IDCODE" Type="6" Size="0">3000000000021</Field>
<Field Name="CAPTION" Type="1" Size="255">Очередь</Field>
<Field Name="PRIORITY" Type="6" Size="0">1</Field>
</Row>
</DATASET>
</result>
</command>
</commands>
</response>
这里是模特
@Root(name = "response", strict = false)
data class NetworkTestContainer(
@field:ElementList(name = "commands")
val commands : List<Command>
) {
@Root(name = "command", strict = false)
data class Command(
@field:Element
val nick : String,
@field:Element(name = "result")
val result : Result
)
@Root(name = "result", strict = false)
data class Result(
@field:Element(name = "DATASET")
val dataSet: DataSet
)
@Root(name = "DATASET", strict = false)
data class DataSet(
@field:Attribute(name = "Version")
val version : String,
@field:Attribute(name = "Class")
val className : String,
@field:Attribute(name = "Name")
val Name : String,
@field:ElementList(inline = true)
val rows : List<Row>
)
@Root(name = "Row", strict = false)
data class Row(
@field:Attribute(name = "Index")
val index : Int,
@field:ElementList(inline = true, entry = "Field")
val fields: List<Field>
// @field:ElementMap(attribute = true, entry = "Field", key = "Name", inline = true)
// val fields : Map<String, String>
)
@Root(name = "Field", strict = false)
data class Field (
@field:Attribute(name = "Name", required = false)
val key : String,
@field:Attribute(name = "Type", required = false)
val type : Int,
@field:Attribute(name = "Size", required = false)
val size : Int,
@get:Text
@set:Text
var text : String
)
}
我对这个库不熟悉,但是我尝试调试它,这是我的发现。
根据the documentation,该库通过使用带有字段/获取器/设置器注释的空构造函数或通过使用构造函数注入+吸收器注释来工作。
在第一种情况下,在创建对象时,您需要摆脱data
修饰符并使用@field:
批注,再加上lateinit var
或其他方法来初始化所有字段。示例:
import org.simpleframework.xml.Attribute
import org.simpleframework.xml.Element
import org.simpleframework.xml.ElementList
import org.simpleframework.xml.Root
import org.simpleframework.xml.core.Persister
@Root(name = "response", strict = false)
class NetworkTestContainer {
@field:ElementList(name = "commands")
lateinit var commands: List<Command>
override fun toString(): String {
return "NetworkTestContainer(commands=$commands)"
}
}
@Root(name = "command", strict = false)
class Command {
@field:Element(name = "nick")
lateinit var nick: String
@field:Element(name = "result")
lateinit var result: Result
override fun toString(): String {
return "Command(nick='$nick', result=$result)"
}
}
@Root(name = "result", strict = false)
class Result {
@field:Element(name = "DATASET")
lateinit var dataSet: DataSet
override fun toString(): String {
return "Result(dataSet=$dataSet)"
}
}
@Root(name = "DATASET", strict = false)
class DataSet {
@field:Attribute(name = "Version")
lateinit var version: String
@field:Attribute(name = "Class")
lateinit var className: String
@field:Attribute(name = "Name")
lateinit var name: String
@field:ElementList(inline = true)
lateinit var rows: List<Row>
override fun toString(): String {
return "DataSet(version='$version', className='$className', name='$name', rows=$rows)"
}
}
@Root(name = "Row", strict = false)
class Row {
@field:Attribute(name = "Index")
var index: Int = 0
@field:ElementList(inline = true, entry = "Field")
lateinit var fields: List<Field>
override fun toString(): String {
return "Row(index=$index, fields=$fields)"
}
// @field:ElementMap(attribute = true, entry = "Field", key = "Name", inline = true)
// val fields : Map<String, String>
}
@Root(name = "Field", strict = false)
class Field {
@field:Attribute(name = "Name", required = false)
lateinit var key: String
@field:Attribute(name = "Type", required = false)
var type: Int = 0
@field:Attribute(name = "Size", required = false)
var size: Int = 0
override fun toString(): String {
return "Field(key='$key', type=$type, size=$size)"
}
}
object Main {
@JvmStatic
fun main(args: Array<String>) {
val deserializer = Persister()
val file = Main::class.java.getResourceAsStream("input.xml")
val container = deserializer.read(NetworkTestContainer::class.java, file)
println(container)
}
}
此打印:
NetworkTestContainer(commands=[Command(nick='QUEUECAUSES_LIST', result=Result(dataSet=DataSet(version='1.0', className='TQueryAdv', name='', rows=[Row(index=1, fields=[Field(key='SHOPID', type=6, size=0), Field(key='IDCODE', type=6, size=0), Field(key='CAPTION', type=1, size=255), Field(key='PRIORITY', type=6, size=0)]), Row(index=2, fields=[Field(key='SHOPID', type=6, size=0), Field(key='IDCODE', type=6, size=0), Field(key='CAPTION', type=1, size=255), Field(key='PRIORITY', type=6, size=0)])])))])
如您所见,这并不理想,但是可以。
一种可能更好的方法涉及使用构造函数注入,这也需要带注释的getter或字段(如上面链接的文档中所指定)。
为了做到这一点,您需要使用@param:
批注(因为您需要注释构造函数参数)和@get:
批注(因为您需要注释getter)。示例:
import org.simpleframework.xml.Attribute
import org.simpleframework.xml.Element
import org.simpleframework.xml.ElementList
import org.simpleframework.xml.Root
import org.simpleframework.xml.Text
import org.simpleframework.xml.core.Persister
@Root(name = "response", strict = false)
data class NetworkTestContainer(
@param:ElementList(name = "commands")
@get:ElementList(name = "commands")
val commands: List<Command>
) {
@Root(name = "command", strict = false)
data class Command(
@param:Element(name="nick")
@get:Element(name="nick")
val nick: String,
@param:Element(name = "result")
@get:Element(name = "result")
val result: Result
)
@Root(name = "result", strict = false)
data class Result(
@param:Element(name = "DATASET")
@get:Element(name = "DATASET")
val dataSet: DataSet
)
@Root(name = "DATASET", strict = false)
data class DataSet(
@param:Attribute(name = "Version")
@get:Attribute(name = "Version")
val version: String,
@param:Attribute(name = "Class")
@get:Attribute(name = "Class")
val className: String,
@param:Attribute(name = "Name")
@get:Attribute(name = "Name")
val Name: String,
@param:ElementList(inline = true)
@get:ElementList(inline = true)
val rows: List<Row>
)
@Root(name = "Row", strict = false)
data class Row(
@param:Attribute(name = "Index")
@get:Attribute(name = "Index")
val index: Int,
@param:ElementList(inline = true, entry = "Field")
@get:ElementList(inline = true, entry = "Field")
val fields: List<Field>
// @field:ElementMap(attribute = true, entry = "Field", key = "Name", inline = true)
// val fields : Map<String, String>
)
@Root(name = "Field", strict = false)
data class Field(
@param:Attribute(name = "Name", required = false)
@get:Attribute(name = "Name", required = false)
val key: String,
@param:Attribute(name = "Type", required = false)
@get:Attribute(name = "Type", required = false)
val type: Int,
@param:Attribute(name = "Size", required = false)
@get:Attribute(name = "Size", required = false)
val size: Int
)
}
object Main {
@JvmStatic
fun main(args: Array<String>) {
val deserializer = Persister()
val file = Main::class.java.getResourceAsStream("input.xml")
val container = deserializer.read(NetworkTestContainer::class.java, file)
println(container)
}
}
这将打印出与上述相同的内容(除了字符串的某些样式差异之外:]
NetworkTestContainer(commands=[Command(nick=QUEUECAUSES_LIST, result=Result(dataSet=DataSet(version=1.0, className=TQueryAdv, Name=, rows=[Row(index=1, fields=[Field(key=SHOPID, type=6, size=0), Field(key=IDCODE, type=6, size=0), Field(key=CAPTION, type=1, size=255), Field(key=PRIORITY, type=6, size=0)]), Row(index=2, fields=[Field(key=SHOPID, type=6, size=0), Field(key=IDCODE, type=6, size=0), Field(key=CAPTION, type=1, size=255), Field(key=PRIORITY, type=6, size=0)])])))])