Skip to content

Commit

Permalink
Merge pull request #59 from fmjsjx/56-let-fastjson2-library-can-readw…
Browse files Browse the repository at this point in the history
…rite-jackson2-jsonnode-values

Let Fastjson2 library can read/write Jackson2 JsonNode values
  • Loading branch information
fmjsjx committed Sep 7, 2023
2 parents 4f05395 + d4d4d43 commit c88a4a1
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 7 deletions.
4 changes: 4 additions & 0 deletions libcommon-json-fastjson2/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ java {
registerFeature("jsoniterSupport") {
usingSourceSet(sourceSets["main"])
}
registerFeature("jackson2Support") {
usingSourceSet(sourceSets["main"])
}
}

dependencies {
Expand All @@ -17,6 +20,7 @@ dependencies {
implementation(project(":libcommon-util"))
api("com.alibaba.fastjson2:fastjson2")
"jsoniterSupportApi"("com.jsoniter:jsoniter")
"jackson2SupportImplementation"(project(":libcommon-json-jackson2"))

testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ public class Fastjson2Library implements JsonLibrary<JSONObject> {
if (ReflectUtil.hasClassForName("com.jsoniter.any.Any")) {
registerJsoniterAny();
}
if (ReflectUtil.hasClassForName("com.github.fmjsjx.libcommon.json.Jackson2Library")) {
registerJackson2Library();
}
}

private static void registerJsoniterAny() {
private static final void registerJsoniterAny() {
var anyClassNames = List.of(
"com.jsoniter.any.Any",
"com.jsoniter.any.LazyAny",
Expand Down Expand Up @@ -98,6 +101,85 @@ private static void registerJsoniterAny() {
}
}

private static final void registerJackson2Library() {
// since 3.6
var jsonNodeClassNames = List.of(
"com.fasterxml.jackson.databind.node.ArrayNode",
"com.fasterxml.jackson.databind.node.BigIntegerNode",
"com.fasterxml.jackson.databind.node.DoubleNode",
"com.fasterxml.jackson.databind.node.DecimalNode",
"com.fasterxml.jackson.databind.node.IntNode",
"com.fasterxml.jackson.databind.node.LongNode",
"com.fasterxml.jackson.databind.node.NullNode",
"com.fasterxml.jackson.databind.node.POJONode",
"com.fasterxml.jackson.databind.node.ShortNode",
"com.fasterxml.jackson.databind.node.TextNode"
);
for (var jsonNodeClassName : jsonNodeClassNames) {
try {
var anyClass = Class.forName(jsonNodeClassName);
JSON.register(anyClass, (jsonWriter, object, fieldName, fieldType, features) -> {
if (object == null) {
jsonWriter.writeNull();
} else {
jsonWriter.writeRaw(com.github.fmjsjx.libcommon.json.Jackson2Library.getInstance().dumpsToString(object));
}
});
} catch (ClassNotFoundException e) {
// skip
}
}
try {
var anyClass = Class.forName("com.fasterxml.jackson.databind.node.ArrayNode");
JSON.register(anyClass, (jsonReader, fieldType, fieldName, features) -> {
if (jsonReader.nextIfNull()) {
return com.fasterxml.jackson.databind.node.NullNode.getInstance();
}
return com.github.fmjsjx.libcommon.json.Jackson2Library.getInstance().loads(jsonReader.readJSONArray().toJSONString(WriteNonStringKeyAsString, WriteNulls));
});
} catch (ClassNotFoundException e) {
// skip
}
try {
var anyClass = Class.forName("com.fasterxml.jackson.databind.node.ObjectNode");
JSON.register(anyClass, (jsonReader, fieldType, fieldName, features) -> {
if (jsonReader.nextIfNull()) {
return com.fasterxml.jackson.databind.node.NullNode.getInstance();
}
return com.github.fmjsjx.libcommon.json.Jackson2Library.getInstance().loads(jsonReader.readJSONObject().toJSONString(WriteNonStringKeyAsString, WriteNulls));
});
} catch (ClassNotFoundException e) {
// skip
}
try {
var anyClass = Class.forName("com.fasterxml.jackson.databind.JsonNode");
JSON.register(anyClass, (jsonReader, fieldType, fieldName, features) -> {
if (jsonReader.nextIfNull()) {
return com.fasterxml.jackson.databind.node.NullNode.getInstance();
}
if (jsonReader.isObject()) {
return com.github.fmjsjx.libcommon.json.Jackson2Library.getInstance().loads(jsonReader.readJSONObject().toJSONString(WriteNonStringKeyAsString, WriteNulls));
}
if (jsonReader.isArray()) {
return com.github.fmjsjx.libcommon.json.Jackson2Library.getInstance().loads(jsonReader.readJSONArray().toJSONString(WriteNonStringKeyAsString, WriteNulls));
}
if (jsonReader.isString()) {
return com.github.fmjsjx.libcommon.json.Jackson2Library.getInstance().loads(JSON.toJSONString(jsonReader.readString(), WriteNonStringKeyAsString, WriteNulls));
}
if (jsonReader.isNumber()) {
return com.github.fmjsjx.libcommon.json.Jackson2Library.getInstance().loads(JSON.toJSONString(jsonReader.readNumber(), WriteNonStringKeyAsString, WriteNulls));
}
return switch (jsonReader.current()) {
case 't', 'f' -> com.fasterxml.jackson.databind.node.BooleanNode.valueOf(jsonReader.readBoolValue());
default ->
com.github.fmjsjx.libcommon.json.Jackson2Library.getInstance().loads(JSON.toJSONString(jsonReader.readAny(), WriteNonStringKeyAsString, WriteNulls));
};
});
} catch (ClassNotFoundException e) {
// skip
}
}

/**
* A JSON exception threw by the {@link Fastjson2Library}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static org.junit.jupiter.api.Assertions.*;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.*;
import com.jsoniter.JsonIterator;
import com.jsoniter.ValueType;
import com.jsoniter.any.Any;
Expand Down Expand Up @@ -50,6 +52,9 @@ public void testLoads() {
assertEquals(2, o.getL1().getAsLong());
assertEquals(3.0, o.getD1().getAsDouble());
assertNull(o.getAny());
assertNull(o.getJn());
assertNull(o.getOn());
assertNull(o.getAn());

// {"l1":2,"d1":3.0}
json = "{\"l1\":2,\"d1\":3.0}";
Expand All @@ -58,7 +63,6 @@ public void testLoads() {
assertTrue(o.getI1().isEmpty());
assertEquals(2, o.getL1().getAsLong());
assertEquals(3.0, o.getD1().getAsDouble());
assertNull(o.getAny());

// {"i1":null,"l1":2,"d1":3.0}
json = "{\"i1\":null,\"l1\":2,\"d1\":3.0}";
Expand All @@ -67,7 +71,6 @@ public void testLoads() {
assertTrue(o.getI1().isEmpty());
assertEquals(2, o.getL1().getAsLong());
assertEquals(3.0, o.getD1().getAsDouble());
assertNull(o.getAny());

// {"i1":1,"d1":3.0}
json = "{\"i1\":1,\"d1\":3.0}";
Expand All @@ -76,7 +79,6 @@ public void testLoads() {
assertEquals(1, o.getI1().getAsInt());
assertTrue(o.getL1().isEmpty());
assertEquals(3.0, o.getD1().getAsDouble());
assertNull(o.getAny());

// {"i1":1,"l1":null,"d1":3.0}
json = "{\"i1\":1,\"l1\":null,\"d1\":3.0}";
Expand All @@ -85,7 +87,6 @@ public void testLoads() {
assertEquals(1, o.getI1().getAsInt());
assertTrue(o.getL1().isEmpty());
assertEquals(3.0, o.getD1().getAsDouble());
assertNull(o.getAny());

// {"i1":1,"l1":2}
json = "{\"i1\":1,\"l1\":2}";
Expand All @@ -94,7 +95,6 @@ public void testLoads() {
assertEquals(1, o.getI1().getAsInt());
assertEquals(2, o.getL1().getAsLong());
assertTrue(o.getD1().isEmpty());
assertNull(o.getAny());

// {"i1":1,"l1":2,"d1":null}
json = "{\"i1\":1,\"l1\":2,\"d1\":null}";
Expand All @@ -103,7 +103,6 @@ public void testLoads() {
assertEquals(1, o.getI1().getAsInt());
assertEquals(2, o.getL1().getAsLong());
assertTrue(o.getD1().isEmpty());
assertNull(o.getAny());

// {"any":null}
json = "{\"any\":null}";
Expand Down Expand Up @@ -152,6 +151,66 @@ public void testLoads() {
assertNotNull(o.getAny());
assertEquals(ValueType.BOOLEAN, o.getAny().valueType());
assertFalse(o.getAny().toBoolean());
// {"jn":null,"on":null,"an":null}
json = "{\"jn\":null,\"on\":null,\"an\":null}";
o = Fastjson2Library.getInstance().loads(json, TestObj.class);
assertNotNull(o);
assertNull(o.getJn());
assertNull(o.getOn());
assertNull(o.getAn());
// {"jn":{"key":"value"},"on":{"key":"value"},"an":[1,2,3]}
json = "{\"jn\":{\"key\":\"value\"},\"on\":{\"key\":\"value\"},\"an\":[1,2,3]}";
o = Fastjson2Library.getInstance().loads(json, TestObj.class);
assertNotNull(o);
assertNotNull(o.getJn());
assertEquals(JsonNodeType.OBJECT, o.getJn().getNodeType());
assertEquals("{\"key\":\"value\"}", o.getJn().toString());
assertNotNull(o.getOn());
assertEquals("{\"key\":\"value\"}", o.getOn().toString());
assertNotNull(o.getAn());
assertEquals("[1,2,3]", o.getAn().toString());
// {"jn":[1,2,3]}
json = "{\"jn\":[1,2,3]}";
o = Fastjson2Library.getInstance().loads(json, TestObj.class);
assertNotNull(o);
assertNotNull(o.getJn());
assertEquals(JsonNodeType.ARRAY, o.getJn().getNodeType());
assertEquals("[1,2,3]", o.getJn().toString());
// {"jn":"This is a string"}
json = "{\"jn\":\"This is a string\"}";
o = Fastjson2Library.getInstance().loads(json, TestObj.class);
assertNotNull(o);
assertNotNull(o.getJn());
assertEquals(JsonNodeType.STRING, o.getJn().getNodeType());
assertEquals("This is a string", o.getJn().textValue());
// {"jn":123}
json = "{\"jn\":123}";
o = Fastjson2Library.getInstance().loads(json, TestObj.class);
assertNotNull(o);
assertNotNull(o.getJn());
assertEquals(JsonNodeType.NUMBER, o.getJn().getNodeType());
assertEquals(123, o.getJn().intValue());
// {"jn":123.4567890123}
json = "{\"jn\":123.4567890123}";
o = Fastjson2Library.getInstance().loads(json, TestObj.class);
assertNotNull(o);
assertNotNull(o.getJn());
assertEquals(JsonNodeType.NUMBER, o.getJn().getNodeType());
assertEquals(123.4567890123, o.getJn().doubleValue());
// {"jn":true}
json = "{\"jn\":true}";
o = Fastjson2Library.getInstance().loads(json, TestObj.class);
assertNotNull(o);
assertNotNull(o.getJn());
assertEquals(JsonNodeType.BOOLEAN, o.getJn().getNodeType());
assertTrue(o.getJn().booleanValue());
// {"jn":false}
json = "{\"jn\":false}";
o = Fastjson2Library.getInstance().loads(json, TestObj.class);
assertNotNull(o);
assertNotNull(o.getJn());
assertEquals(JsonNodeType.BOOLEAN, o.getJn().getNodeType());
assertFalse(o.getJn().booleanValue());
} catch (Exception e) {
fail(e);
}
Expand All @@ -165,6 +224,10 @@ public static class TestObj {

private Any any;

private JsonNode jn;
private ObjectNode on;
private ArrayNode an;

public OptionalInt getI1() {
return i1;
}
Expand Down Expand Up @@ -197,6 +260,30 @@ public void setAny(Any any) {
this.any = any;
}

public JsonNode getJn() {
return jn;
}

public void setJn(JsonNode jn) {
this.jn = jn;
}

public ObjectNode getOn() {
return on;
}

public void setOn(ObjectNode on) {
this.on = on;
}

public ArrayNode getAn() {
return an;
}

public void setAn(ArrayNode an) {
this.an = an;
}

}

@Test
Expand Down Expand Up @@ -225,4 +312,30 @@ public void testWriteJsoniterAny() {
);
}

@Test
public void testWriteJsonNode() {
var object = new JSONObject();
object.put("null", NullNode.getInstance());
object.put("string", TextNode.valueOf("abc"));
object.put("short", ShortNode.valueOf((short) 123));
object.put("int", IntNode.valueOf(123456));
object.put("long", LongNode.valueOf(1234567890123L));
object.put("double", DoubleNode.valueOf(123.456));
object.put("true", BooleanNode.TRUE);
object.put("false", BooleanNode.FALSE);
object.put("object", JsonNodeFactory.instance.objectNode().put("key", "value"));
object.put("array", JsonNodeFactory.instance.arrayNode().add(0));

assertEquals(
"""
{"null":null,"string":"abc","short":123,"int":123456,"long":1234567890123,"double":123.456,"true":{"array":false,"bigDecimal":false,"bigInteger":false,"binary":false,"boolean":true,"containerNode":false,"double":false,"empty":true,"float":false,"floatingPointNumber":false,"int":false,"integralNumber":false,"long":false,"missingNode":false,"nodeType":"BOOLEAN","null":false,"number":false,"object":false,"pojo":false,"short":false,"textual":false,"valueNode":true},"false":{"array":false,"bigDecimal":false,"bigInteger":false,"binary":false,"boolean":true,"containerNode":false,"double":false,"empty":true,"float":false,"floatingPointNumber":false,"int":false,"integralNumber":false,"long":false,"missingNode":false,"nodeType":"BOOLEAN","null":false,"number":false,"object":false,"pojo":false,"short":false,"textual":false,"valueNode":true},"object":{"key":"value"},"array":[0]}""",
Fastjson2Library.getInstance().dumpsToString(object)
);
assertArrayEquals(
"""
{"null":null,"string":"abc","short":123,"int":123456,"long":1234567890123,"double":123.456,"true":{"array":false,"bigDecimal":false,"bigInteger":false,"binary":false,"boolean":true,"containerNode":false,"double":false,"empty":true,"float":false,"floatingPointNumber":false,"int":false,"integralNumber":false,"long":false,"missingNode":false,"nodeType":"BOOLEAN","null":false,"number":false,"object":false,"pojo":false,"short":false,"textual":false,"valueNode":true},"false":{"array":false,"bigDecimal":false,"bigInteger":false,"binary":false,"boolean":true,"containerNode":false,"double":false,"empty":true,"float":false,"floatingPointNumber":false,"int":false,"integralNumber":false,"long":false,"missingNode":false,"nodeType":"BOOLEAN","null":false,"number":false,"object":false,"pojo":false,"short":false,"textual":false,"valueNode":true},"object":{"key":"value"},"array":[0]}""".getBytes(StandardCharsets.UTF_8),
Fastjson2Library.getInstance().dumpsToBytes(object)
);
}

}

0 comments on commit c88a4a1

Please sign in to comment.