question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Is it possible to encode/decode non-primitive types inside Mapper?

See original GitHub issue

A project I am working on uses Google’s Firestore NoSQL database, and the Android SDK takes a Map<String, Any> to create or update a record in the database.

The problem I’m working in is how to translate something like this:

data class Foo(val string: String, val number: Int, val timestamp: Instant)

into a map like this:

{
    "string" to "whatever string value",
    "number" to 1234,
    "timestamp" to [corresponding instance of java.util.Date]  // java.time.Instant instance translated to java.util.Date instance
}

Using encoders/decoders like the ones described here allow me to go straight from a data class to a map, which is great.

My problem is that I don’t know how to translate Instant into a non-primitive. I can obviously write a custom Serializer for Instant like so

@Serializer(forClass = Instant::class)
object InstantSerializer : KSerializer<Instant> {
        override val descriptor: SerialDescriptor =
            StringDescriptor.withName("Instant")

        override fun serialize(output: Encoder, obj: Instant) {
            output.encodeString(obj.toString())
        }

        override fun deserialize(input: Decoder): Instant {
            return Instant.parse(input.decodeString())
}
    

but then the map looks like

{
    "string" to "whatever string value",
    "number" to 1234,
    "timestamp" to "2019-03-11T00:00:00Z"
}

Which would be great for sending a HTTP request or something along those lines. The problem is that if the Firestore SDK picks up a java.util.Date in the Map<String,Any> that you pass it when creating/updating an object, it will store it differently than if it is a String representation of that time.

To sum it up, I’m wondering if it is possible to encode to/decode from an arbitrary, non-primitive type?

PS - I realize that timestamps in the ISO8601 format most likely can be sorted and queried against just as efficiently as any custom Date object that Firestore is using on their end, this is just the simplest example. There are others that would not work quite as well

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
sandwwraithcommented, Mar 18, 2019

I think currentTag property is what you’re looking into.

0reactions
jeffreyfjohnsoncommented, Mar 18, 2019

In case anyone else stumbles upon this, this is my final encoder class:

class MapEncoder(val map: MutableMap<String, Any> = mutableMapOf()) : NamedValueEncoder() {

    override fun beginCollection(
        desc: SerialDescriptor,
        collectionSize: Int,
        vararg typeParams: KSerializer<*>
    ): CompositeEncoder {
        encodeTaggedInt(nested("size"), collectionSize)
        return this
    }

    override fun encodeTaggedValue(tag: String, value: Any) {
        map[tag] = value
    }

    override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) {
        when {
            serializer is InstantSerializer && value is Instant -> {
                map.put(currentTag, value)
                endStructure(serializer.descriptor) // need this, otherwise tag/key mapping gets messed up
            }
            else -> super.encodeSerializableValue(serializer, value)
        }
    }
}

Thank you to @sandwwraith for all the help

Read more comments on GitHub >

github_iconTop Results From Across the Web

Encoding and Decoding Custom Types - Apple Developer
Encode and Decode Automatically​​ The simplest way to make a type codable is to declare its properties using types that are already Codable...
Read more >
How to handle encoded and decoded version of the same c# ...
I'm using hashids.org for this and have built helper methods to quickly decode/encode properties in my automapper mapping.
Read more >
Guide to Java URL Encoding/Decoding - Baeldung
In this tutorial, we'll focus on how to encode/decode the URL or form data so that it adheres to the spec and transmits...
Read more >
Advanced Encoding and Decoding Techniques in Go
The first technique we are going to examine is to create a new type and convert our data to/from that type before encoding...
Read more >
Tutorial: How to Encode and Decode JSON Data? - ZIO
The ZIO JSON library provides a default implementation for most of the primitive types like Int , String , Boolean , etc. Let's...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found