Related to JSON serialization using Moshi. For a J...
# http4k
g
Related to JSON serialization using Moshi. For a JSON like this consider the properties other than
attributes
are dynamic:
Copy code
"records": [
  {
    "attributes": {
      "type": "...",
      "url": "..."
    },
    "Id": "...",
    "Name": "...",
    "...": "..."
  }
]
How can I Desrialize or Unmarshall into a Dataclass like this such that all the dynamic keys go into a
recordBody: Map<String, Any>
Copy code
@JsonClass(generateAdapter = true)
data class Body(
  val records: List<Record>,
)

@JsonClass(generateAdapter = true)
data class Record(
  val attributes: Attributes,
  val recordBody: Map<String, Any>
)

@JsonClass(generateAdapter = true)
data class Attributes(
  val type: String,
  val url: String
)
I cannot find an annotation similar to
@JsonAnySetter
a
You might be able to get a better moshi responses from the moshi community, but it's fairly easy to register a custom marshaller to your http4k
AutoMarshalling
Example: Custom Moshi Marshaller Example: Register Custom Marshaller
g
Thanks for the examples, it helped me come up with a Custom Moshi marshaller
Copy code
class RecordAdapterFactory : JsonAdapter.Factory {
    override fun create(type: Type, annotations: Set<Annotation?>, moshi: Moshi): JsonAdapter<*>? {
      if (type != Record::class.java) {
        return null
      }
      val attributeAdapter = moshi.nextAdapter<Attributes>(this, Attributes::class.java, Util.NO_ANNOTATIONS)
      return object : JsonAdapter<Record>() {
        override fun fromJson(reader: JsonReader): Record {
          reader.beginObject()
          var attributes = Attributes("", "")
          val recordBody = mutableMapOf<String, String>()
          while(reader.hasNext()) {
            when(val nextName = reader.nextName()) {
              "attributes" -> attributes = attributeAdapter.fromJson(reader.nextString()) ?: Attributes("", "")
              else -> recordBody[nextName] = reader.nextString()
            }
          }
          return Record(attributes, recordBody)
        }

        override fun toJson(writer: JsonWriter, value: Record?) {
          writer.beginObject()
          writer.name("attributes").value(attributeAdapter.toJson(value?.attributes))
          value?.recordBody?.entries?.forEach { writer.name(it.key).value(it.value) }
          writer.endObject()
        }
      }
    }
  }