DataFixerUpper
DataFixerUpper copied to clipboard
JsonOps.convertTo explodes on JsonNulls
public static void main(String[] args) {
JsonObject j = new JsonObject();
j.add("test", JsonNull.INSTANCE);
System.out.println(JsonOps.INSTANCE.convertTo(JsonOps.INSTANCE, j)); //should return a copy of `j`
}
fails with
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.google.gson.JsonElement.getAsJsonPrimitive()" because "input" is null
at com.mojang.serialization.JsonOps.convertTo(JsonOps.java:50)
at com.mojang.serialization.JsonOps.convertTo(JsonOps.java:24)
at com.mojang.serialization.DynamicOps.lambda$convertMap$27(DynamicOps.java:255)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1845)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at com.mojang.serialization.JsonOps.createMap(JsonOps.java:275)
at com.mojang.serialization.JsonOps.createMap(JsonOps.java:24)
at com.mojang.serialization.DynamicOps.convertMap(DynamicOps.java:254)
at com.mojang.serialization.JsonOps.convertTo(JsonOps.java:42)
at agency.highlysuspect.apathy.rule.CodecUtil.main(CodecUtil.java:145)
It appears there is a check for instanceof JsonNulls:
https://github.com/Mojang/DataFixerUpper/blob/c100ef03c2ab321e5de4f25ffbe277e924aa7ca5/src/main/java/com/mojang/serialization/JsonOps.java#L47-L50
But it doesn't work, because DynamicOps#getJsonValues, as well as other methods like getStream and getList, filter JsonNulls to actual nulls.
https://github.com/Mojang/DataFixerUpper/blob/c100ef03c2ab321e5de4f25ffbe277e924aa7ca5/src/main/java/com/mojang/serialization/JsonOps.java#L218
The workaround i'm using in my current project (making a Codec out of something that has toJson and fromJson methods, where toJson sometimes returns JsonObjects containing JsonNulls) is just preprocessing the entire JsonObject and filtering out nulls in objects/arrays, which isn't strictly correct because it loses the distinction between "key present with null value" and "absent key", but in practice it tends to work for what im using it for