diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.kt index 2928a48df..7276cce4e 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.kt @@ -20,6 +20,8 @@ */ package com.vitorpamplona.quartz.nip01Core.core +import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate +import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor import kotlinx.serialization.json.Json interface OptimizedSerializable @@ -31,6 +33,10 @@ expect object OptimizedJsonMapper { fun fromJsonToTagArray(json: String): Array> + fun fromJsonToEventTemplate(json: String): EventTemplate + + fun fromJsonToRumor(json: String): Rumor + fun toJson(tags: Array>): String inline fun fromJsonTo(json: String): T diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplate.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplate.kt index 1b55f0eb0..81d422c5a 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplate.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplate.kt @@ -38,7 +38,7 @@ class EventTemplate( fun toJson(): String = OptimizedJsonMapper.toJson(this) companion object { - fun fromJson(json: String): EventTemplate = OptimizedJsonMapper.fromJsonTo>(json) + fun fromJson(json: String): EventTemplate = OptimizedJsonMapper.fromJsonToEventTemplate(json) } } diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEvent.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEvent.kt index b5c2bf611..9e5157d7d 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEvent.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip46RemoteSigner/BunkerResponseEvent.kt @@ -34,6 +34,14 @@ class BunkerResponseEvent( id: String, result: String, error: String? = null, - ) = BunkerResponseEvent(id, Event.fromJson(result)) + ): BunkerResponseEvent { + val event = Event.fromJson(result) + + if (event.sig.isEmpty()) { + throw IllegalStateException("Invalid event") + } + + return BunkerResponseEvent(id, event) + } } } diff --git a/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.ios.kt b/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.ios.kt index c73cec34b..ae709b411 100644 --- a/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.ios.kt +++ b/quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.ios.kt @@ -20,6 +20,9 @@ */ package com.vitorpamplona.quartz.nip01Core.core +import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate +import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor + actual object OptimizedJsonMapper { actual fun fromJson(json: String): Event = TODO("Not yet implemented") @@ -27,6 +30,10 @@ actual object OptimizedJsonMapper { actual fun fromJsonToTagArray(json: String): Array> = TODO("Not yet implemented") + actual fun fromJsonToEventTemplate(json: String): EventTemplate = TODO("Not yet implemented") + + actual fun fromJsonToRumor(json: String): Rumor = TODO("Not yet implemented") + actual fun toJson(tags: Array>): String = TODO("Not yet implemented") actual inline fun fromJsonTo(json: String): T = TODO("Not yet implemented") diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.jvmAndroid.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.jvmAndroid.kt index e934d8537..7ee005d79 100644 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.jvmAndroid.kt +++ b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/core/OptimizedJsonMapper.jvmAndroid.kt @@ -21,6 +21,8 @@ package com.vitorpamplona.quartz.nip01Core.core import com.vitorpamplona.quartz.nip01Core.jackson.JacksonMapper +import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate +import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor actual object OptimizedJsonMapper { inline fun runCatching(parsingAction: () -> T): T = @@ -37,6 +39,10 @@ actual object OptimizedJsonMapper { actual fun fromJsonToTagArray(json: String): Array> = runCatching { JacksonMapper.fromJsonToTagArray(json) } + actual fun fromJsonToRumor(json: String): Rumor = runCatching { JacksonMapper.fromJsonToRumor(json) } + + actual fun fromJsonToEventTemplate(json: String): EventTemplate = runCatching { JacksonMapper.fromJsonToEventTemplate(json) } + actual fun toJson(tags: Array>): String = JacksonMapper.toJson(tags) actual inline fun fromJsonTo(json: String): T = runCatching { JacksonMapper.fromJsonTo(json) } diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializer.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializer.kt index 284a6459a..e989ffc5a 100644 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializer.kt +++ b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventDeserializer.kt @@ -21,13 +21,49 @@ package com.vitorpamplona.quartz.nip01Core.jackson import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.core.JsonToken import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.deser.std.StdDeserializer import com.vitorpamplona.quartz.nip01Core.core.Event +import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.Kind +import com.vitorpamplona.quartz.nip01Core.core.TagArray +import com.vitorpamplona.quartz.utils.EventFactory class EventDeserializer : StdDeserializer(Event::class.java) { + val tagsDeserializer = TagArrayDeserializer() + + val emptyArray = emptyArray>() + override fun deserialize( - jp: JsonParser, + p: JsonParser, ctxt: DeserializationContext, - ): Event = EventManualDeserializer.fromJson(jp.codec.readTree(jp)) + ): Event { + var id: HexKey = "" + var pubKey: HexKey = "" + var createdAt: Long = 0 + var kind: Kind = 0 + var tags: TagArray = emptyArray + var content: String = "" + var sig: HexKey = "" + + while (p.nextToken() != JsonToken.END_OBJECT) { + val fieldName = p.currentName() + p.nextToken() + + when (fieldName.hashCode()) { + 3355 -> id = p.text.intern() + -977424830 -> pubKey = p.text.intern() + 1369680106 -> createdAt = p.longValue + 3292052 -> kind = p.intValue + 3552281 -> tags = tagsDeserializer.deserialize(p, ctxt) + 951530617 -> content = p.text + 113873 -> sig = p.text + else -> p.skipChildren() + } + } + + // NPE on purpose. If the object isn't fully filled, it should throw. + return EventFactory.create(id, pubKey, createdAt, kind, tags, content, sig) + } } diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventManualDeserializer.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventManualDeserializer.kt deleted file mode 100644 index adcc10e8c..000000000 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/EventManualDeserializer.kt +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2025 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.vitorpamplona.quartz.nip01Core.jackson - -import com.fasterxml.jackson.databind.JsonNode -import com.vitorpamplona.quartz.nip01Core.core.Event -import com.vitorpamplona.quartz.utils.EventFactory - -class EventManualDeserializer { - companion object { - fun fromJson(jsonObject: JsonNode): Event = - EventFactory.create( - id = jsonObject.get("id").asText().intern(), - pubKey = jsonObject.get("pubkey").asText().intern(), - createdAt = jsonObject.get("created_at").asLong(), - kind = jsonObject.get("kind").asInt(), - tags = TagArrayManualDeserializer.fromJson(jsonObject.get("tags")), - content = jsonObject.get("content").asText(), - sig = jsonObject.get("sig").asText(), - ) - } -} diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/JacksonMapper.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/JacksonMapper.kt index d1111304c..66f8c9b61 100644 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/JacksonMapper.kt +++ b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/JacksonMapper.kt @@ -22,11 +22,12 @@ package com.vitorpamplona.quartz.nip01Core.jackson import com.fasterxml.jackson.core.json.JsonReadFeature import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.JavaType import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.databind.node.ArrayNode import com.fasterxml.jackson.databind.node.ObjectNode import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import com.fasterxml.jackson.module.kotlin.readValue import com.vitorpamplona.quartz.nip01Core.core.Event import com.vitorpamplona.quartz.nip01Core.core.OptimizedSerializable @@ -58,6 +59,7 @@ import com.vitorpamplona.quartz.nip47WalletConnect.jackson.ResponseDeserializer import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor import com.vitorpamplona.quartz.nip59Giftwrap.rumors.jackson.RumorDeserializer import com.vitorpamplona.quartz.nip59Giftwrap.rumors.jackson.RumorSerializer +import kotlinx.serialization.json.JsonNull.content import java.io.InputStream class JacksonMapper { @@ -67,6 +69,8 @@ class JacksonMapper { val mapper = jacksonObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, false) + .configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false) .enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature()) .setDefaultPrettyPrinter(defaultPrettyPrinter) .registerModule( @@ -98,11 +102,21 @@ class JacksonMapper { .addDeserializer(BunkerResponse::class.java, BunkerResponseDeserializer()), ) - fun fromJson(json: String): Event = mapper.readValue(json) + /** + * Shortcuts + */ + val eventTypeInstance: JavaType = mapper.typeFactory.constructType(jacksonTypeRef()) + val tagArrayTypeInstance: JavaType = mapper.typeFactory.constructType(jacksonTypeRef()) + val rumorTypeInstance: JavaType = mapper.typeFactory.constructType(jacksonTypeRef()) + val eventTemplateTypeInstance: JavaType = mapper.typeFactory.constructType(jacksonTypeRef>()) - fun fromJson(json: JsonNode): Event = EventManualDeserializer.fromJson(json) + fun fromJson(json: String): Event = mapper.readValue(json, eventTypeInstance) - fun fromJsonToTagArray(json: String): TagArray = mapper.readValue(json) + fun fromJsonToTagArray(json: String): TagArray = mapper.readValue(json, tagArrayTypeInstance) + + fun fromJsonToRumor(json: String): Rumor = mapper.readValue(json, rumorTypeInstance) + + fun fromJsonToEventTemplate(json: String): EventTemplate = mapper.readValue(json, eventTemplateTypeInstance) inline fun fromJsonTo(json: String): T = mapper.readValue(json) diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayManualDeserializer.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayManualDeserializer.kt deleted file mode 100644 index 1aa2c4b30..000000000 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/jackson/TagArrayManualDeserializer.kt +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2025 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.vitorpamplona.quartz.nip01Core.jackson - -import com.fasterxml.jackson.databind.JsonNode -import com.vitorpamplona.quartz.nip01Core.core.TagArray - -class TagArrayManualDeserializer { - companion object { - fun fromJson(tagArray: JsonNode): TagArray = - tagArray.toTypedArray { tag -> - tag.toTypedArray { s -> - if (s.isNull) { - "" - } else { - s.asText().intern() - } - } - } - } -} diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/MessageDeserializer.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/MessageDeserializer.kt index dbc03c469..dfc0faa25 100644 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/MessageDeserializer.kt +++ b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toClient/MessageDeserializer.kt @@ -25,9 +25,11 @@ import com.fasterxml.jackson.core.JsonToken import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.deser.std.StdDeserializer -import com.vitorpamplona.quartz.nip01Core.jackson.EventManualDeserializer +import com.vitorpamplona.quartz.nip01Core.jackson.EventDeserializer class MessageDeserializer : StdDeserializer(Message::class.java) { + val eventDeserializer = EventDeserializer() + override fun deserialize( jp: JsonParser, ctxt: DeserializationContext, @@ -42,11 +44,10 @@ class MessageDeserializer : StdDeserializer(Message::class.java) { EventMessage.LABEL -> { val subId = jp.nextTextValue() jp.nextToken() - val event: JsonNode = jp.codec.readTree(jp) EventMessage( subId = subId, - event = EventManualDeserializer.fromJson(event), + event = eventDeserializer.deserialize(jp, ctxt), ) } diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CommandDeserializer.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CommandDeserializer.kt index f84a2b884..623c55031 100644 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CommandDeserializer.kt +++ b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/relay/commands/toRelay/CommandDeserializer.kt @@ -23,15 +23,16 @@ package com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.core.JsonToken import com.fasterxml.jackson.databind.DeserializationContext -import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.deser.std.StdDeserializer import com.fasterxml.jackson.databind.node.ObjectNode -import com.vitorpamplona.quartz.nip01Core.jackson.EventManualDeserializer +import com.vitorpamplona.quartz.nip01Core.jackson.EventDeserializer import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip01Core.relay.filters.ManualFilterDeserializer import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent class CommandDeserializer : StdDeserializer(Command::class.java) { + val eventDeserializer = EventDeserializer() + override fun deserialize( jp: JsonParser, ctxt: DeserializationContext, @@ -77,10 +78,9 @@ class CommandDeserializer : StdDeserializer(Command::class.java) { EventCmd.LABEL -> { jp.nextToken() - val event: JsonNode = jp.codec.readTree(jp) EventCmd( - event = EventManualDeserializer.fromJson(event), + event = eventDeserializer.deserialize(jp, ctxt), ) } @@ -91,9 +91,8 @@ class CommandDeserializer : StdDeserializer(Command::class.java) { AuthCmd.LABEL -> { jp.nextToken() - val event: JsonNode = jp.codec.readTree(jp) AuthCmd( - event = EventManualDeserializer.fromJson(event) as RelayAuthEvent, + event = eventDeserializer.deserialize(jp, ctxt) as RelayAuthEvent, ) } diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateDeserializer.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateDeserializer.kt index 94e69cf39..3a641aa86 100644 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateDeserializer.kt +++ b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateDeserializer.kt @@ -21,13 +21,38 @@ package com.vitorpamplona.quartz.nip01Core.signers import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.core.JsonToken import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.deser.std.StdDeserializer import com.vitorpamplona.quartz.nip01Core.core.Event +import com.vitorpamplona.quartz.nip01Core.jackson.TagArrayDeserializer class EventTemplateDeserializer : StdDeserializer>(EventTemplate::class.java) { + val tagsDeserializer = TagArrayDeserializer() + val emptyArray = emptyArray>() + override fun deserialize( - jp: JsonParser, + p: JsonParser, ctxt: DeserializationContext, - ): EventTemplate = EventTemplateManualDeserializer.fromJson(jp.codec.readTree(jp)) + ): EventTemplate { + var createdAt = 0L + var kind = 0 + var tags = emptyArray + var content = "" + + while (p.nextToken() != JsonToken.END_OBJECT) { + val fieldName = p.currentName() + p.nextToken() + + when (fieldName.hashCode()) { + 1369680106 -> createdAt = p.longValue + 3292052 -> kind = p.intValue + 3552281 -> tags = tagsDeserializer.deserialize(p, ctxt) + 951530617 -> content = p.text + else -> p.skipChildren() + } + } + + return EventTemplate(createdAt, kind, tags, content) + } } diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateManualDeserializer.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateManualDeserializer.kt deleted file mode 100644 index 614e9db4b..000000000 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip01Core/signers/EventTemplateManualDeserializer.kt +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2025 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.vitorpamplona.quartz.nip01Core.signers - -import com.fasterxml.jackson.databind.JsonNode -import com.vitorpamplona.quartz.nip01Core.core.Event -import com.vitorpamplona.quartz.nip01Core.jackson.TagArrayManualDeserializer - -class EventTemplateManualDeserializer { - companion object { - fun fromJson(jsonObject: JsonNode): EventTemplate = - EventTemplate( - createdAt = jsonObject.get("created_at").asLong(), - kind = jsonObject.get("kind").asInt(), - tags = TagArrayManualDeserializer.fromJson(jsonObject.get("tags")), - content = jsonObject.get("content").asText(), - ) - } -} diff --git a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/jackson/RumorDeserializer.kt b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/jackson/RumorDeserializer.kt index ff5c67c19..74b8c160b 100644 --- a/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/jackson/RumorDeserializer.kt +++ b/quartz/src/jvmAndroid/kotlin/com/vitorpamplona/quartz/nip59Giftwrap/rumors/jackson/RumorDeserializer.kt @@ -21,28 +21,43 @@ package com.vitorpamplona.quartz.nip59Giftwrap.rumors.jackson import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.core.JsonToken import com.fasterxml.jackson.databind.DeserializationContext -import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.deser.std.StdDeserializer -import com.vitorpamplona.quartz.nip01Core.jackson.TagArrayManualDeserializer +import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.TagArray +import com.vitorpamplona.quartz.nip01Core.jackson.TagArrayDeserializer import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor -import com.vitorpamplona.quartz.utils.asIntOrNull -import com.vitorpamplona.quartz.utils.asLongOrNull -import com.vitorpamplona.quartz.utils.asTextOrNull class RumorDeserializer : StdDeserializer(Rumor::class.java) { + val tagsDeserializer = TagArrayDeserializer() + override fun deserialize( - jp: JsonParser, + p: JsonParser, ctxt: DeserializationContext, ): Rumor { - val jsonObject: JsonNode = jp.codec.readTree(jp) - return Rumor( - id = jsonObject.get("id")?.asTextOrNull()?.intern(), - pubKey = jsonObject.get("pubkey")?.asTextOrNull()?.intern(), - createdAt = jsonObject.get("created_at")?.asLongOrNull(), - kind = jsonObject.get("kind")?.asIntOrNull(), - tags = TagArrayManualDeserializer.fromJson(jsonObject.get("tags")), - content = jsonObject.get("content")?.asTextOrNull(), - ) + var id: HexKey? = null + var pubKey: HexKey? = null + var createdAt: Long? = null + var kind: Int? = null + var tags: TagArray? = null + var content: String? = null + + while (p.nextToken() != JsonToken.END_OBJECT) { + val fieldName = p.currentName() + p.nextToken() + + when (fieldName.hashCode()) { + 3355 -> id = p.text.intern() + -977424830 -> pubKey = p.text.intern() + 1369680106 -> createdAt = p.longValue + 3292052 -> kind = p.intValue + 3552281 -> tags = tagsDeserializer.deserialize(p, ctxt) + 951530617 -> content = p.text + else -> p.skipChildren() + } + } + + return Rumor(id, pubKey, createdAt, kind, tags, content) } }