Coder Social home page Coder Social logo

How to serialize into a Json ? about knbt HOT 9 CLOSED

Ayfri avatar Ayfri commented on July 22, 2024
How to serialize into a Json ?

from knbt.

Comments (9)

BenWoodworth avatar BenWoodworth commented on July 22, 2024 1

Hey! I think you have the right approach, but there was a bug that made @Serializable sealed interfaces (like NbtTag) not work correctly out of the box. I'm planning on having that fixed in knbt v0.12, since serializable sealed interfaces are now supported, but it might be a bit.

I can get you a more complete answer later, but something like this might work for now. (this is from memory, so it might not be quite right)

val polymorphicNbtSerializersModule = SerializersModule {
    polymorphic(NbtTag::class, NbtTag.serializer()) {
        subclass(NbtByte::class, NbtByte.serializer())
        subclass(NbtShort::class, NbtShort.serializer())
        // ...and all the other NbtTag types
    }
}

val json = Json {
    // ...
    serializersModule = polymorphicNbtSerializersModule
}

I'll play around with it later to get something that working :)

from knbt.

BenWoodworth avatar BenWoodworth commented on July 22, 2024

Although on second thought I'm not sure that'll work. The NbtTag serializers require the NbtEncoder/Decoder:

encoder.asNbtEncoder().encodeByte(value.value)

Same as how the JsonElements require the JsonEncoder/Decoder:

https://github.com/Kotlin/kotlinx.serialization/blob/dc950f5098162a3f8dd742d04b95f9a0405470e1/formats/json/commonMain/src/kotlinx/serialization/json/JsonElementSerializers.kt#L40-L41

https://github.com/Kotlin/kotlinx.serialization/blob/dc950f5098162a3f8dd742d04b95f9a0405470e1/formats/json/commonMain/src/kotlinx/serialization/json/JsonElementSerializers.kt#L192

from knbt.

BenWoodworth avatar BenWoodworth commented on July 22, 2024

So you'd need a custom serializer, which I can help you with.

How do you feel about storing the NBT as a JSON string value? Writing it as SNBT is probably the easiest thing to do

from knbt.

Ayfri avatar Ayfri commented on July 22, 2024

It's complicated, because I'm serializing a data class DataPack, containing a serializable data class Pack, containing a property description which is a NbtTag (it's for generating the pack.mcmeta from datapacks). So if I serialize all this to a SNBT, it won't be a valid JSON.

from knbt.

BenWoodworth avatar BenWoodworth commented on July 22, 2024

Ah, gotcha! Just got off work so I'm starting to look into it.

Is this the one you're talking about? And changing it from String to NbtTag
https://github.com/Ayfri/Datapack-DSL/blob/e57be5bb68330216958d23034730ff5616704dd3/src/main/kotlin/DataPack.kt#L16

I haven't done much with data packs personally, but the pack.mcmeta page makes it look like description is also JSON. Is that right? I might be missing something

from knbt.

BenWoodworth avatar BenWoodworth commented on July 22, 2024

Also that's an awesome project! I love what I'm seeing 😁

from knbt.

Ayfri avatar Ayfri commented on July 22, 2024

Thanks !
It can be a string, a NBTList or a NBTCompound, as it is considered as a Text Component.

from knbt.

BenWoodworth avatar BenWoodworth commented on July 22, 2024

How's this look? Serializing seems to work like a charm. I played around with deserializing for a good two hours and... yeah. It's tricky... trying to figure out the best way to map things around 😬

It seems like you only need to serialize for now though so here's a start:

import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.serialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*
import net.benwoodworth.knbt.*

private object NbtAsJsonTextComponentSerializer : KSerializer<NbtTag> {
	@OptIn(ExperimentalSerializationApi::class)
	override val descriptor: SerialDescriptor =
		SerialDescriptor("TextComponentJsonSerializer", serialDescriptor<JsonElement>())

	override fun serialize(encoder: Encoder, value: NbtTag): Unit =
		encoder.encodeSerializableValue(JsonElement.serializer(), value.toJsonElement())

	override fun deserialize(decoder: Decoder): NbtTag =
		throw UnsupportedOperationException("Deserializing not supported")

	private fun NbtTag.toJsonElement(): JsonElement = when (this) {
		is NbtCompound -> JsonObject(mapValues { it.value.toJsonElement() })
		is NbtList<*> -> JsonArray(map { it.toJsonElement() })
		is NbtByteArray -> JsonArray(map { JsonPrimitive(it) })
		is NbtIntArray -> JsonArray(map { JsonPrimitive(it) })
		is NbtLongArray -> JsonArray(map { JsonPrimitive(it) })

		is NbtString -> JsonPrimitive(value)

		is NbtByte -> when(value) { // Or just convert to number?
			0.toByte() -> JsonPrimitive(false)
			1.toByte() -> JsonPrimitive(true)
			else -> JsonPrimitive(value)
		}

		is NbtShort -> JsonPrimitive(value)
		is NbtInt -> JsonPrimitive(value)
		is NbtLong -> JsonPrimitive(value)
		is NbtFloat -> JsonPrimitive(value)
		is NbtDouble -> JsonPrimitive(value)
	}

//    private fun JsonElement.toNbtTag(): NbtCompound = when (this) {
//        is JsonObject -> NbtCompound(mapValues { (_, value) -> value })
//
//        is JsonArray -> // NbtList elements must all be the same type
//
//        is JsonPrimitive -> when (val value = contentOrNull) {
//            null -> error("$value is not supported in text components")
//            else -> NbtString(value)
//        }
//    }
}

@Serializable
data class Pack(
	var packFormat: Int,

	@Serializable(NbtAsJsonTextComponentSerializer::class)
	var description: NbtTag,
)

from knbt.

Ayfri avatar Ayfri commented on July 22, 2024

Nice, it works well, thank you so much ! Can't wait to have it integrated by default :)

from knbt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.