Moshi Parse Flat Json as Nested Object

Oct 21, 2018

I would like to parse the following json

{     "name":"Hello",   "media_key":"I am Key",   "media_blob_url":"I am Url",   "media_blob_key": null}

into the following object

class BlobType(        @Json(name = "media_key") var mediaKey: String? = null,        @Json(name = "media_blob_url") var mediaBlobUrl: String? = null,        @Json(name = "media_blob_key") var mediaBlobKey: String? = null        )class Item (        var name: String? = null,        @Json(name="media_key") var blob: BlobType? = null)class AnotherItem (        var name: String? = null,        var address: String? = null,        @Json(name="media_key") var blob: BlobType? = null)

and convert the object to flat json again.

NOTE: Something like Android Room Embedded where one object could be used to store multiple columns.

I probably need to write an Adapter for this purpose.

The main problem is adapter expect a single field to return a single result only (either a string or an object), but now I need to write a ToJson which convert a single object into 3 json fields and another FromJson to combine 3 json fields into a single object.

Somehow I manage to hack/hardcode ToJson which convert one object into 3 fields.

class BlobTypeJsonAdapter {        /*        @FromJson        fun blogTypeFromJson(reader: JsonReader): BlobType {            val item = BlobType()            item.mediaKey = reader.nextString()            System.out.println("nextName="+reader.nextName())            return item        }         */        @ToJson        fun blogTypeToJson(writer: JsonWriter, item: BlobType) {            writer.value(item.mediaKey)            writer.name("media_blog_key").value(item.mediaBlobKey)            writer.name("media_blog_url").value(item.mediaBlobUrl)        }}
val moshi = = Moshi.Builder()        .add(BlobTypeJsonAdapter())        .add(KotlinJsonAdapterFactory())        .build()val adapter = moshi.adapter<Item>(Item::class.java)val item = Item(name="Hello", blob = BlobType(mediaKey = "I am Key", mediaBlobUrl = "I am Url"))val jsonString = adapter.toJson(item)

Output

{     "name":"Hello",   "media_key":"I am Key",   "media_blob_url":"I am Url"}

I didn't persuit this idea further because I feel the approach and solution is "unnatural" (merge multiple fields into object) and might introduce future confusion.

NOTE: Technically, I could make those fields private and create a object property with getter/setter to return a object based on these private fields.

NOTE: I could use EventJsonAdapter example, but would need to write an adapter for each class (Item and AnotherItem) and could not reuse the shared portion of BlobType only.

Besides, my moshi-fu is not strong enough and further experimentation will consume more time and introduce more complexity vs the benefit gained.

References:

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.