b

    bjonnh

    1 year ago
    I'm sure this has been asked 20 times, but how can I serialize something like :
    data class Vega(
        val background: StringOrMoreComplex
    )
    e

    ephemient

    1 year ago
    depends on what is StringOrMoreComplex
    b

    bjonnh

    1 year ago
    either a String or something @Serializable
    I know at compile time what it can be
    e

    ephemient

    1 year ago
    if it were
    @Serializable
    data class Vega<T>(
        val background: T
    )
    you'd have no issues (at least not here). that level of knowing at compile-time?
    b

    bjonnh

    1 year ago
    The Json is either {background: "#FFFFFF"} or {background: {somemoreJson}}
    ok I though about doing that way, let me try that
    I tried to understand how polymorphism work
    but all I could get was {background: {something}} not the direct string
    e

    ephemient

    1 year ago
    this isn't polymorphism. you'd need to know ahead of time, at compile time, if you're serializing/deserializing a Vega<String> or a Vega<JsonObject>
    if you do want polymorphism at runtime, that would require writing a custom serializer
    b

    bjonnh

    1 year ago
    is there an example of something like that? I may want to do that at some point
    e

    ephemient

    1 year ago
    I don't think kotlinx.serialization would be very happy with it changing shape between String and Object, though - you can probably make it work on JSON by doing some preprocessing, but it won't work on other formats
    b

    bjonnh

    1 year ago
    this is only for JSON.
    The problem is that I have many types that are StringOrSomethingSerializable
    This is what I try to make a DSL for: https://vega.github.io/vega/docs/specification/
    I want to be able to generate JSON with that format
    maybe I need to use a more dynamic JSON library for that. But I liked the idea to have a clean data classes to describe the format
    ok I managed to write a custom serializer that works well enough
    I'll do the deserializer just in case as well
    I'm not super fan of the deserializer, as I'm doing a try catch when trying to do a decodeString that then tries to decode the object
    but it seems to work really well so far
    I'm also not sure what the descriptor should be in those cases
    e

    ephemient

    1 year ago
    b

    bjonnh

    1 year ago
    hum let me share what I did
    (I had a way with sealed classes instead of the interface before, was just trying the inline classes here)
    e

    ephemient

    1 year ago
    try { decoder.decodeString()
    can cause issues as the decoder isn't rewindable
    b

    bjonnh

    1 year ago
    the json one is not?
    ok it seemed to have worked in my tests in which case can it fail?
    e

    ephemient

    1 year ago
    well, with Json it happens to work ok because of how it's tokenized, but IMO doing some pre-processing on JsonElement to get it into the form that kotlinx.serialization.json likes is safer IMO
    b

    bjonnh

    1 year ago
    ok I'll check your way as well
    especially with triple unions
    would your way work out of the JVM as well?
    e

    ephemient

    1 year ago
    yeah, your approach will have some issues with that with multiple object types
    yes, this is all common
    b

    bjonnh

    1 year ago
    great
    thanks !
    e

    ephemient

    1 year ago
    if that ends up not working for you, then look into JsonContentPolymorphicSerializer
    b

    bjonnh

    1 year ago
    Now I'm confused
    it works even without the serializer
    oh I see why… 🤦‍♂️
    With your approach I get an error about the tSerializer parameter being null in JsonTransformingSerializer.<init>
    oh I missed the @file
    is there a way to make that global to a json object?
    e

    ephemient

    1 year ago
    unfortunately not
    b

    bjonnh

    1 year ago
    I can't get your solution to work, it still tells me that the Background.serializer() is null
    oh nevermind I forgot a with…
    e

    ephemient

    1 year ago
    well ok, if you poke into
    @InternalSerializationApi
    then this is doable. also if you use Kotlin 1.5's
    sealed interface
    (usable on Kotlin 1.4.3x if you add
    kotlinOptions.languageVersion = "1.5"
    ) then you can have
    Signal
    in multiple sealed hierarchies
    b

    bjonnh

    1 year ago
    I can't seem to be able to use your serializer
    even with the @file… annotation
    e

    ephemient

    1 year ago
    really? that file runs here with no issues...
    b

    bjonnh

    1 year ago
    How do you get Signal shared between multiple classes?
    oooh yes with the sealed interface
    your last way works, I'm not a fan of using the internalApi
    but it works beautifuly
    With your way I don't know how to make the deserializer for objects that can be three different things
    I come back to the same issue I had initially (and why I used try/catch)
    maybe it is safer as we are working on an element?
    I don't seem to need the internalapi annotation
    I got a version with the triple union working, but that's again using a try/catch
    e

    ephemient

    1 year ago
    buildSerialDescriptor("Name", SerialKind.SEALED)
    required
    @Internal
    , but I played around with it and it seems that
    buildClassSerialDescriptor("Name")
    works just fine, public API
    updated to show off a few other things as well
    b

    bjonnh

    1 year ago
    thanks, this is really cool, I don't think I would have found all that by myself
    oh you built even the Autosize part, I was making that one
    You'll be an author on that lib if you want 😉
    I thought about the "signal" in element, but I was worried this could appear in it by other means, but maybe I was over cautious
    e

    ephemient

    1 year ago
    nah I was just checking that various things with
    @SerialName
    would work as expected
    b

    bjonnh

    1 year ago
    Thanks for your help, it make plots now!