Line 5: |
Line 5: |
| == Serialization and Deserialization == | | == Serialization and Deserialization == |
| | | |
− | The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or a Tag, and to deserialize an serialized object back to its proper java type. This is accomplished with <code>Codec#encodeStart</code> and <code>Codec#parse</code>, respectively. Given a Codec<SomeJavaType> and a DynamicOps<SomeSerializedType>, we can convert instances of SomeJavaType to instances of SomeSerializedType and back. | + | The primary use for Codecs is to serialize java objects to some serialized type, such as a JsonElement or a Tag, and to deserialize a serialized object back to its proper java type. This is accomplished with <code>Codec#encodeStart</code> and <code>Codec#parse</code>, respectively. Given a Codec<SomeJavaType> and a DynamicOps<SomeSerializedType>, we can convert instances of SomeJavaType to instances of SomeSerializedType and back. |
| | | |
| Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult: | | Each of these methods take a [[DynamicOps]] instance and an instance of the object we are serializing or deserializing, and returns a DataResult: |
Line 18: |
Line 18: |
| | | |
| // deserialize some Tag instance back to a proper java object | | // deserialize some Tag instance back to a proper java object |
− | DataResult<SomeJavaType> result = someCodec.parse(NBTOps.INSTANCE, someTag ); | + | DataResult<SomeJavaType> result = someCodec.parse(NBTOps.INSTANCE, someTag); |
| | | |
| // serialize some java object to a JsonElement | | // serialize some java object to a JsonElement |
Line 92: |
Line 92: |
| As previously mentioned, we can use <code>Codec.INT</code> for the integer codec, and <code>Registry.ITEM</code> for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one. | | As previously mentioned, we can use <code>Codec.INT</code> for the integer codec, and <code>Registry.ITEM</code> for the Item codec. We don't have a builtin codec for list-of-blockpos, but we can use BlockPos.CODEC to create one. |
| | | |
− | == Lists == | + | ==Lists== |
| The <code>Codec#listOf</code> instance method can be used to generate a codec for a List from an existing codec: | | The <code>Codec#listOf</code> instance method can be used to generate a codec for a List from an existing codec: |
| | | |
| <syntaxhighlight lang="java"> | | <syntaxhighlight lang="java"> |
| // BlockPos.CODEC is a Codec<BlockPos> | | // BlockPos.CODEC is a Codec<BlockPos> |
− | Codec<List<BlockPos>> = BlockPos.CODEC.listOf(); | + | Codec<List<BlockPos>> blockPosListCodec = BlockPos.CODEC.listOf(); |
| </syntaxhighlight> | | </syntaxhighlight> |
| | | |
Line 166: |
Line 166: |
| Codec.STRING.fieldOf("name").codec()); | | Codec.STRING.fieldOf("name").codec()); |
| | | |
− | JsonElement encodedPair = BOXED_INT_CODEC.encodeStart(JsonOps.INSTANCE, Pair.of(5, "cheese").result().get(); | + | JsonElement encodedPair = PAIR_CODEC.encodeStart(JsonOps.INSTANCE, Pair.of(5, "cheese").result().get(); |
| </syntaxhighlight> | | </syntaxhighlight> |
| This codec serializes the above value to: | | This codec serializes the above value to: |
Line 267: |
Line 267: |
| * BlockPlacer and BlockPlacerType | | * BlockPlacer and BlockPlacerType |
| * ConfiguredDecorator and FeatureDecorator | | * ConfiguredDecorator and FeatureDecorator |
| + | |
| + | === Registering MapCodecCodecs for Dispatch Subcodecs === |
| + | |
| + | When registering a subcodec to any dispatch codec registry, the registered subcodec should be an instance of MapCodecCodec, or the subcodec will be nested in its own object when serialized. |
| + | |
| + | For example, suppose we register a single-field subcodec, where we use fieldOf-and-xmap to convert an int to our int-holding Thing: |
| + | |
| + | <syntaxhighlight lang="java"> |
| + | public record Thing(int n){} |
| + | public static Codec<Thing> CODEC = Codec.INT.fieldOf("n").codec().xmap(Thing::new, Thing::n); |
| + | </syntaxhighlight> |
| + | |
| + | This results in this json when serialized: |
| + | |
| + | <syntaxhighlight lang="json"> |
| + | "some_thing": |
| + | { |
| + | "type": "ourmod:thing", |
| + | "value": { |
| + | "n": 5 |
| + | } |
| + | } |
| + | </syntaxhighlight> |
| + | |
| + | This occurs because xmap does not produce a MapCodecCodec, and if this nested object is not desired, then our registered subcodec must be a MapCodecCodec. |
| + | |
| + | However, fieldOf() produces a MapCodec, which has a codec() method, which does produce a MapCodecCodec. We can rearrange our codec builder, which then produces a cleaner json: |
| + | |
| + | <syntaxhighlight lang="java"> |
| + | public static Codec<Thing> CODEC = Codec.INT // Primitive codec |
| + | .fieldOf("n") // MapCodec |
| + | .xmap(Thing::new, Thing::n) // MapCodec |
| + | .codec(); // MapCodecCodec! That's what we want. |
| + | </syntaxhighlight> |
| + | |
| + | <syntaxhighlight lang="json"> |
| + | "some_thing": |
| + | { |
| + | "type": "ourmod:thing", |
| + | "n": 5 |
| + | } |
| + | </syntaxhighlight> |
| + | |
| + | RecordCodecBuilder also produces MapCodecCodecs. |
| | | |
| =External Links= | | =External Links= |
| * [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository] | | * [https://github.com/Mojang/DataFixerUpper/blob/master/src/main/java/com/mojang/serialization/Codec.java Codecs in Mojang's official public DataFixerUpper repository] |
| * [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs] | | * [https://kvverti.github.io/Documented-DataFixerUpper/snapshot/com/mojang/serialization/Codec.html#flatXmap-java.util.function.Function-java.util.function.Function- Unofficial Codec Javadocs] |