All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.http4k.format.ConfigurableMoshi.kt Maven / Gradle / Ivy

package org.http4k.format

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import okio.buffer
import okio.source
import org.http4k.core.Body
import org.http4k.core.ContentType
import org.http4k.core.ContentType.Companion.APPLICATION_JSON
import org.http4k.lens.BiDiBodyLensSpec
import org.http4k.lens.BiDiMapping
import org.http4k.lens.BiDiWsMessageLensSpec
import org.http4k.lens.ContentNegotiation
import org.http4k.lens.ContentNegotiation.Companion.None
import org.http4k.lens.string
import org.http4k.websocket.WsMessage
import java.io.InputStream
import java.math.BigDecimal
import java.math.BigInteger
import kotlin.reflect.KClass

open class ConfigurableMoshi(
    builder: Moshi.Builder,
    val defaultContentType: ContentType = APPLICATION_JSON
) : AutoMarshalling() {

    private val moshi: Moshi = builder.build()

    override fun asFormatString(input: Any): String = moshi.adapter(input.javaClass).toJson(input)

    fun  asJsonString(t: T, c: KClass): String = moshi.adapter(c.java).toJson(t)

    override fun  asA(input: String, target: KClass): T = moshi.adapter(target.java).fromJson(input)!!

    override fun  asA(input: InputStream, target: KClass): T = moshi.adapter(target.java).fromJson(
        input.source().buffer()
    )!!

    inline fun  Body.Companion.auto(
        description: String? = null,
        contentNegotiation: ContentNegotiation = None,
        contentType: ContentType = defaultContentType
    ): BiDiBodyLensSpec =
        autoBody(description, contentNegotiation, contentType)

    inline fun  autoBody(
        description: String? = null,
        contentNegotiation: ContentNegotiation = None,
        contentType: ContentType = defaultContentType
    ): BiDiBodyLensSpec =
        Body.string(contentType, description, contentNegotiation).map({ asA(it, T::class) }, {
            asFormatString(it)
        })

    inline fun  WsMessage.Companion.auto(): BiDiWsMessageLensSpec =
        WsMessage.string().map({ it.asA(T::class) }, { asFormatString(it) })
}

fun Moshi.Builder.asConfigurable() = object : AutoMappingConfiguration {
    override fun  int(mapping: BiDiMapping) = adapter(mapping, { value(it) }, { nextInt() })
    override fun  long(mapping: BiDiMapping) =
        adapter(mapping, { value(it) }, { nextLong() })

    override fun  double(mapping: BiDiMapping) =
        adapter(mapping, { value(it) }, { nextDouble() })

    override fun  bigInteger(mapping: BiDiMapping) =
        adapter(mapping, { value(it) }, { nextLong().toBigInteger() })

    override fun  bigDecimal(mapping: BiDiMapping) =
        adapter(mapping, { value(it) }, { nextDouble().toBigDecimal() })

    override fun  boolean(mapping: BiDiMapping) =
        adapter(mapping, { value(it) }, { nextBoolean() })

    override fun  text(mapping: BiDiMapping) =
        adapter(mapping, { value(it) }, { nextString() })

    private fun  adapter(
        mapping: BiDiMapping,
        write: JsonWriter.(IN) -> Unit,
        read: JsonReader.() -> IN
    ) =
        apply {
            add(mapping.clazz, object : JsonAdapter() {
                override fun fromJson(reader: JsonReader) = mapping.invoke(reader.read())

                override fun toJson(writer: JsonWriter, value: OUT?) {
                    value?.let { writer.write(mapping(it)) } ?: writer.nullValue()
                }
            }.nullSafe())
        }

    // add the Kotlin adapter last, as it will hjiack our custom mappings otherwise
    override fun done() =
        [email protected](KotlinJsonAdapterFactory()).add(Unit::class.java, UnitAdapter)
}

private object UnitAdapter : JsonAdapter() {
    override fun fromJson(reader: JsonReader) {
        reader.readJsonValue(); Unit
    }

    override fun toJson(writer: JsonWriter, value: Unit?) {
        value?.let { writer.beginObject().endObject() } ?: writer.nullValue()
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy