Kotlinx.serialization: JSON: write type inside json-object rather than in array

Created on 12 Dec 2017  路  5Comments  路  Source: Kotlin/kotlinx.serialization

Looks like in current implementation objects with polymorphic types are serialized as

[TYPE, { ...OBJECT... }]

It will be more prettily if such objects are serialized as

{
   "@class": TYPE
   ... OBJECT ...
}

Note if the @class is first field in json object then this is may be implemented in single pass parse as for now.

feature

Most helpful comment

@class should be a configurable field name. E.g. in Jackson:

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME, 
  include = JsonTypeInfo.As.PROPERTY, 
  property = "type")
@JsonSubTypes({ 
  @Type(value = Car.class, name = "car"), 
  @Type(value = Truck.class, name = "truck") 
})

This would be highly useful - things that get JSON-serialized are more often than not algebraic data types.

All 5 comments

@class should be a configurable field name. E.g. in Jackson:

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME, 
  include = JsonTypeInfo.As.PROPERTY, 
  property = "type")
@JsonSubTypes({ 
  @Type(value = Car.class, name = "car"), 
  @Type(value = Truck.class, name = "truck") 
})

This would be highly useful - things that get JSON-serialized are more often than not algebraic data types.

Seems KInput needs to be able to peek for values in order to implement a serial loader that can read polymorphic values with @class.

Another example in klaxon "Polymorphic classes" https://github.com/cbeust/klaxon#polymorphic-classes

[
    { "type": "rectangle", "width": 100, "height": 50 },
    { "type": "circle", "radius": 20}
]
@TypeFor(field = "type", adapter = ShapeTypeAdapter::class)
open class Shape(val type: String)
data class Rectangle(val width: Int, val height: Int): Shape()
data class Circle(val radius: Int): Shape()



md5-881a01ddce6f356dcfb770e063349047



class ShapeTypeAdapter: TypeAdapter<Shape> {
    override fun classFor(type: Any): KClass<out Shape> = when(type as String) {
        "rectangle" -> Rectangle::class
        "circle" -> Circle::class
        else -> throw IllegalArgumentException("Unknown type: $type")
    }
}

Also, will be very useful to support multi-level inheritance.
An example will be for articles, it can be published or draft, and it can also have types: text, link, video.

[
    { "state": "draft", "type": "link", "url": "http..." },
    { "state": "published", "type": "link", "url": "http..." },
    { "state": "published", "type": "text", "content": "xyz" }
]

Any plans for this?

Was this page helpful?
0 / 5 - 0 ratings