What would be the recommended approach to deserial...
# serialization
j
What would be the recommended approach to deserialize a JSON structure that has two different keys that represent the same values? Examples are in the thread. Edit: (One possible solution is in the thread, turns out I wasn’t reading the error message correctly 😬)
The example JSON I get from the server:
Copy code
{ 
  "data": [ 
    { 
       "id": "thing1",
       "someArrayOfItems": ["one", "two"], 
       "other": [...SpecialType] 
    }, 
    { 
       "id": "thing2", 
       "some-array-of-items": ["four", "five"], 
       "other": [...SpecialType] 
    } 
  ] 
}
The output that I would like to achieve would be:
Copy code
@Serializable
data class Things(
  val id: String,
  val someArrayOfItems: Array<String>,
  val other: List<SpecialType>
)

@Serializable
data class SpecialType(
  val name: String
)
Where
someArrayOfItems
would contain the array from either
someArrayOfItems
or
someArrayOfItems
. I’ve been trying to use
JsonTransformingSerializer
to “rename”
some-array-of-items
before the deserialization happens but am having trouble with the serializers for the
SpecialType
not being used or something because when I use the transforming serializer then it doesn’t know how to handle “name”. I’m working to simplify the use case and will put an example of what I’ve tried here shortly.
Well my shortened example seems to work fine so maybe my original code has a flaw somewhere… I’ll clean the example up and post for future reference and see if I can narrow down what my original code is doing different 🙄
I ended up using something like this as my transforming serializer.
Copy code
object TempTransformingSerializer : JsonTransformingSerializer<Temp>(Temp.serializer()) {
    override fun transformDeserialize(element: JsonElement): JsonElement {
        val someArrayOfItemsWithDashes = element.jsonObject["some-array-of-items"]
        return when {
            someArrayOfItemsWithDashes != null -> {
                buildJsonObject {
                    element.jsonObject.entries.forEach { (key, value) ->
                        when (key) {
                            "some-array-of-items" -> putJsonArray("someArrayOfItems") {
                                value.jsonArray.forEach { add(it) }
                            }
                            else -> put(key, value)
                        }
                    }
                }
            }
            else -> super.transformDeserialize(element)
        }
    }
}
The input JSON was:
Copy code
{
  "data": [
    {
      "someValue": "value1",
      "temp": {
        "id": "thing1",
        "someArrayOfItems": [
          "one",
          "two"
        ],
        "other": [
          {
            "name_thing": "first thing"
          }
        ]
      }
    },
    {
      "someValue": "value2",
      "temp": {
        "id": "thing2",
        "some-array-of-items": [
          "four",
          "five"
        ],
        "other": [
          {
            "name_thing": "second thing"
          }
        ]
      }
    }
  ]
}
The classes I defined were:
Copy code
@Serializable
data class TopLevel(
    val data: List<SecondLevel>
)

@Serializable
data class SecondLevel(
    val someValue: String,
    @Serializable(with = TempTransformingSerializer::class)
    val temp: Temp
)

@Serializable
data class Temp(
    val id: String,
    val someArrayOfItems: List<String>,
    val other: List<Other>
)

@Serializable
data class Other(
    @SerialName("name_thing")
    val name: String
)
d
There's a
JsonNames
that allows you to provide alternative names for fields.
💯 1
👍 1
j
Wow, guess I missed that in the docs. Works like a charm, thanks!