I am using Json.decodeFromString<User>("json string")
(https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md)
model is like
data class User(val id: String, val name: String, val assets: List<Asset>)
data class Asset(val id: String, val sku: String, val name: String)
but input json is like
{
"data": {
"id": "userId",
"name": "userName",
"body": {
"assets": [
{
"data": {
"id": "assetId",
"sku": "assetSku",
"name": "assetName"
}
}
]
}
}
}
How can I parse json with serializer? Seems not able to parse with delegate and surrogate serializers easily.
CodePudding user response:
Your POJO seems to be wrong , every field needs to have name corresponding to json value , or use GSON's SerializedName
annotation and Parse sing Gson.
Your User POJO should look something like this,
data class User (
@SerializedName("data") var data : UserData
)
data class UserData(
@SerializedName("id") var id : String,
@SerializedName("name") var name : String,
@SerializedName("body") var body : Body
)
data class Body (
@SerializedName("assets") var assets : List<Assets>
)
data class Assets (
@SerializedName("data") var data : AssetsData
)
data class AssetsData(
@SerializedName("id") var id : String,
@SerializedName("sku") var sku : String,
@SerializedName("name") var name : String
)
for serializing and deserializing
dependencies {
implementation 'com.google.code.gson:gson:2.8.9'
}
val gson = Gson()
val jsonValue = gson.toJson(User)
val jsonToUser = gson.fromJson(jsonValue ,User::class.java)
CodePudding user response:
Read about https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md#under-the-hood-experimental
Tried something like this:
@Serializable(with = AssetSerializer::class)
data class Asset(val id: String, val sku: String, val name: String)
@Serializable(with = UserSerializer::class)
data class User(val id: String, val name: String, val assets: List<Asset>)
object AssetSerializer: KSerializer<Asset> {
override val descriptor: SerialDescriptor =
buildClassSerialDescriptor("Asset") {
element("data", buildClassSerialDescriptor("data") {
element("id", String.serializer().descriptor)
element("sku", String.serializer().descriptor)
element("name", String.serializer().descriptor)
})
}
override fun serialize(encoder: Encoder, value: Asset) {
require(encoder is JsonEncoder)
encoder.encodeJsonElement(buildJsonObject {
put("data", buildJsonObject {
put("id", value.id)
put("sku", value.sku)
put("name", value.name)
})
})
}
override fun deserialize(decoder: Decoder): Asset {
require(decoder is JsonDecoder)
val root = decoder.decodeJsonElement()
val element = root.jsonObject["data"]!!
return Asset(
id = element.jsonObject["id"]!!.jsonPrimitive.content,
sku = element.jsonObject["sku"]!!.jsonPrimitive.content,
name = element.jsonObject["name"]!!.jsonPrimitive.content,
)
}
}
object UserSerializer: KSerializer<User> {
override val descriptor: SerialDescriptor =
buildClassSerialDescriptor("User") {
element("data", buildClassSerialDescriptor("data") {
element("id", String.serializer().descriptor)
element("name", String.serializer().descriptor)
element("body", buildClassSerialDescriptor("body") {
element("assets", ListSerializer(Asset.serializer()).descriptor)
})
})
}
override fun serialize(encoder: Encoder, value: User) {
require(encoder is JsonEncoder)
encoder.encodeJsonElement(buildJsonObject {
put("data", buildJsonObject {
put("id", value.id)
put("name", value.name)
put("body", buildJsonObject {
put("assets", JsonArray(value.assets.map { asset ->
encoder.json.encodeToJsonElement(asset)
}))
})
})
})
}
override fun deserialize(decoder: Decoder): User {
require(decoder is JsonDecoder)
val root = decoder.decodeJsonElement()
val element = root.jsonObject["data"]!!
val assets = element
.jsonObject["body"]!!
.jsonObject["assets"]!!
.jsonArray
.map { asset ->
decoder.json.decodeFromJsonElement(asset)
}
return Asset(
id = element.jsonObject["id"]!!.jsonPrimitive.content,
name = element.jsonObject["name"]!!.jsonPrimitive.content,
assets = assets,
)
}
}