More correctly parses null and default values from NIP-55 using Jackson

This commit is contained in:
Vitor Pamplona
2025-11-11 14:00:17 -05:00
parent 5f88249be6
commit 8c3ab80e47
22 changed files with 186 additions and 49 deletions
@@ -27,6 +27,7 @@ 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.readValue
import com.vitorpamplona.quartz.nip01Core.jackson.InliningTagArrayPrettyPrinter
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.results.IntentResult
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.results.IntentResultJsonDeserializer
@@ -50,9 +51,9 @@ object JsonMapperNip55 {
.addSerializer(Permission::class.java, PermissionSerializer()),
)
inline fun <reified T> fromJsonTo(json: String): T = defaultMapper.readValue(json, T::class.java)
inline fun <reified T> fromJsonTo(json: String): T = defaultMapper.readValue<T>(json)
inline fun <reified T> fromJsonTo(json: InputStream): T = defaultMapper.readValue(json, T::class.java)
inline fun <reified T> fromJsonTo(json: InputStream): T = defaultMapper.readValue<T>(json)
fun toJson(event: ArrayNode): String = defaultMapper.writeValueAsString(event)
@@ -34,7 +34,7 @@ class DecryptZapResponse {
)
fun parse(intent: IntentResult): SignerResult.RequestAddressed<ZapEventDecryptionResult> {
if (intent.rejected) {
if (intent.rejected == true) {
return SignerResult.RequestAddressed.ManuallyRejected()
}
val eventJson = intent.result
@@ -33,7 +33,7 @@ class DeriveKeyResponse {
)
fun parse(intent: IntentResult): SignerResult.RequestAddressed<DerivationResult> {
if (intent.rejected) {
if (intent.rejected == true) {
return SignerResult.RequestAddressed.ManuallyRejected()
}
val newPrivateKey = intent.result
@@ -32,7 +32,7 @@ class Nip04DecryptResponse {
)
fun parse(intent: IntentResult): SignerResult.RequestAddressed<DecryptionResult> {
if (intent.rejected) {
if (intent.rejected == true) {
return SignerResult.RequestAddressed.ManuallyRejected()
}
val plaintext = intent.result
@@ -32,7 +32,7 @@ class Nip04EncryptResponse {
)
fun parse(intent: IntentResult): SignerResult.RequestAddressed<EncryptionResult> {
if (intent.rejected) {
if (intent.rejected == true) {
return SignerResult.RequestAddressed.ManuallyRejected()
}
@@ -32,7 +32,7 @@ class Nip44DecryptResponse {
)
fun parse(intent: IntentResult): SignerResult.RequestAddressed<DecryptionResult> {
if (intent.rejected) {
if (intent.rejected == true) {
return SignerResult.RequestAddressed.ManuallyRejected()
}
val plaintext = intent.result
@@ -32,7 +32,7 @@ class Nip44EncryptResponse {
)
fun parse(intent: IntentResult): SignerResult.RequestAddressed<EncryptionResult> {
if (intent.rejected) {
if (intent.rejected == true) {
return SignerResult.RequestAddressed.ManuallyRejected()
}
val ciphertext = intent.result
@@ -39,7 +39,7 @@ class SignResponse {
intent: IntentResult,
unsignedEvent: Event,
): SignerResult.RequestAddressed<SignResult> {
if (intent.rejected) {
if (intent.rejected == true) {
return SignerResult.RequestAddressed.ManuallyRejected()
}
@@ -31,16 +31,17 @@ data class IntentResult(
val result: String? = null,
val event: String? = null,
val id: String? = null,
val rejected: Boolean = false,
val rejected: Boolean? = false,
) : OptimizedSerializable {
fun toJson(): String = JsonMapperNip55.toJson(this)
fun toIntent(): Intent {
val intent = Intent()
intent.putExtra("id", id)
intent.putExtra("result", result)
intent.putExtra("event", event)
intent.putExtra("package", `package`)
if (id != null) intent.putExtra("id", id)
if (result != null) intent.putExtra("result", result)
if (event != null) intent.putExtra("event", event)
if (`package` != null) intent.putExtra("package", `package`)
if (rejected != null) intent.putExtra("rejected", rejected)
return intent
}
@@ -51,7 +52,12 @@ data class IntentResult(
result = data.getStringExtra("result"),
event = data.getStringExtra("event"),
`package` = data.getStringExtra("package"),
rejected = data.extras?.containsKey("rejected") == true,
rejected =
if (data.extras?.containsKey("rejected") == true) {
data.getBooleanExtra("rejected", false)
} else {
null
},
)
fun fromJson(json: String): IntentResult = JsonMapperNip55.fromJsonTo<IntentResult>(json)
@@ -24,6 +24,8 @@ import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.vitorpamplona.quartz.utils.asBooleanOrNull
import com.vitorpamplona.quartz.utils.asTextOrNull
class IntentResultJsonDeserializer : StdDeserializer<IntentResult>(IntentResult::class.java) {
override fun deserialize(
@@ -31,12 +33,13 @@ class IntentResultJsonDeserializer : StdDeserializer<IntentResult>(IntentResult:
ctxt: DeserializationContext,
): IntentResult {
val jsonObject: JsonNode = jp.codec.readTree(jp)
return IntentResult(
`package` = jsonObject.get("package")?.asText()?.intern(),
result = jsonObject.get("result")?.asText(),
event = jsonObject.get("event")?.asText(),
id = jsonObject.get("id")?.asText()?.intern(),
rejected = jsonObject.get("rejected")?.asBoolean() ?: false,
`package` = jsonObject.get("package")?.asTextOrNull()?.intern(),
result = jsonObject.get("result")?.asTextOrNull(),
event = jsonObject.get("event")?.asTextOrNull(),
id = jsonObject.get("id")?.asTextOrNull()?.intern(),
rejected = jsonObject.get("rejected")?.asBooleanOrNull(),
)
}
}
@@ -35,7 +35,7 @@ class IntentResultJsonSerializer : StdSerializer<IntentResult>(IntentResult::cla
result.result?.let { gen.writeStringField("result", it) }
result.event?.let { gen.writeStringField("event", it) }
result.id?.let { gen.writeStringField("id", it) }
result.rejected.let { gen.writeBooleanField("rejected", it) }
result.rejected?.let { gen.writeBooleanField("rejected", it) }
gen.writeEndObject()
}
}