Skip to content

Commit

Permalink
Merge pull request #48 from fmjsjx/44-jsoniterlibrary-support-jsonobj…
Browse files Browse the repository at this point in the history
…ectjsonarray-encodingdecoding

JsoniterLibrary support JSONObject/JSONArray encoding/decoding
  • Loading branch information
fmjsjx committed Aug 11, 2023
2 parents f09ee04 + bf2a3ab commit a9ee416
Show file tree
Hide file tree
Showing 4 changed files with 258 additions and 0 deletions.
5 changes: 5 additions & 0 deletions libcommon-json-jsoniter/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ java {
registerFeature("jackson2Support") {
usingSourceSet(sourceSets["main"])
}
registerFeature("fastjson2Support") {
usingSourceSet(sourceSets["main"])
}
}

dependencies {
Expand All @@ -15,11 +18,13 @@ dependencies {
api(project(":libcommon-json"))
api("com.jsoniter:jsoniter")
"jackson2SupportImplementation"(project(":libcommon-json-jackson2"))
"fastjson2SupportImplementation"(project(":libcommon-json-fastjson2"))

testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.apache.logging.log4j:log4j-slf4j-impl")
testImplementation(project(":libcommon-json-jackson2"))
testImplementation(project(":libcommon-json-fastjson2"))

}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package com.github.fmjsjx.libcommon.json;

import com.jsoniter.ValueType;
import com.jsoniter.any.Any;
import com.jsoniter.output.JsonStream;
import com.jsoniter.spi.Encoder;
import com.jsoniter.spi.JsonException;
import com.jsoniter.spi.JsoniterSpi;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* <a href="https://github.com/alibaba/fastjson2">{@code Fastjson2}</a> support for jsoniter.
*
* @author MJ Fang
* @since 3.6
*/
public final class Fastjson2Support {

private static final Throwable UNAVAILABILITY_CAUSE;

static {
Throwable cause = null;

try {
Class.forName("com.github.fmjsjx.libcommon.json.Fastjson2Library");
} catch (ClassNotFoundException e) {
cause = e;
}

UNAVAILABILITY_CAUSE = cause;
}

/**
* Returns {@code true} if and only if the {@code libcommon-json-fastjson2} is available.
*
* @return {@code true} if and only if the {@code libcommon-json-fastjson2} is available.
*/
public static boolean isAvailable() {
return UNAVAILABILITY_CAUSE == null;
}

/**
* Ensure that {@code libcommon-json-fastjson2} is available.
*
* @throws UnsupportedOperationException if unavailable
*/
public static void ensureAvailability() {
if (UNAVAILABILITY_CAUSE != null) {
throw new UnsupportedOperationException("Fastjson2Library is unavailable", UNAVAILABILITY_CAUSE);
}
}

/**
* Returns the cause of unavailability of {@code libcommon-json-fastjson2}.
*
* @return the cause if unavailable. {@code null} if available.
*/
public static Throwable unavailabilityCause() {
return UNAVAILABILITY_CAUSE;
}

/**
* Enable all <a href="https://github.com/alibaba/fastjson2">{@code Fastjson2}</a> supports.
*/
public static void enableAll() {
ensureAvailability();
Fastjson2JSONObjectSupport.enable();
Fastjson2JSONArraySupport.enable();
}

private Fastjson2Support() {
}

private static final class Fastjson2Encoder implements Encoder.ReflectionEncoder {

private static final Fastjson2Encoder INSTANCE = new Fastjson2Encoder();

@Override
public Any wrap(Object obj) {
return JsoniterLibrary.getInstance().loads(Fastjson2Library.getInstance().dumpsToBytes(obj));
}

@Override
public void encode(Object obj, JsonStream stream) throws IOException {
if (obj == null) {
stream.writeNull();
} else {
stream.write(Fastjson2Library.getInstance().dumpsToBytes(obj));
}
}

private Fastjson2Encoder() {
}

}

/**
* <a href="https://github.com/alibaba/fastjson2">{@code Fastjson2}</a> {@code JSONObject} support.
*/
public static final class Fastjson2JSONObjectSupport {

private static final AtomicBoolean enabled = new AtomicBoolean();

/**
* Returns {@code true} if {@code Fastjson2JSONObjectSupport} is enabled, {@code false} otherwise.
*
* @return {@code true} if {@code Fastjson2JSONObjectSupport} is enabled, {@code false} otherwise
*/
public static boolean enabled() {
return enabled.get();
}

/**
* Enable the {@code Fastjson2JSONObjectSupport}.
*/
public static void enable() {
if (enabled.compareAndSet(false, true)) {
JsoniterSpi.registerTypeEncoder(com.alibaba.fastjson2.JSONObject.class, Fastjson2Encoder.INSTANCE);
JsoniterSpi.registerTypeDecoder(com.alibaba.fastjson2.JSONObject.class, iter -> {
var any = iter.readAny();
if (any.valueType() == ValueType.NULL) {
return null;
} else if (any.valueType() == ValueType.OBJECT) {
return Fastjson2Library.getInstance().loads(any.toString());
}
throw new JsonException("type mismatch, expected OBJECT but was " + any.valueType());
});
}
}

private Fastjson2JSONObjectSupport() {
}

}

/**
* <a href="https://github.com/alibaba/fastjson2">{@code Fastjson2}</a> {@code JSONArray} support.
*/
public static final class Fastjson2JSONArraySupport {

private static final AtomicBoolean enabled = new AtomicBoolean();

/**
* Returns {@code true} if {@code Fastjson2JSONArraySupport} is enabled, {@code false} otherwise.
*
* @return {@code true} if {@code Fastjson2JSONArraySupport} is enabled, {@code false} otherwise
*/
public static boolean enabled() {
return enabled.get();
}

/**
* Enable the {@code Fastjson2JSONArraySupport}.
*/
public static void enable() {
if (enabled.compareAndSet(false, true)) {
JsoniterSpi.registerTypeEncoder(com.alibaba.fastjson2.JSONArray.class, Fastjson2Encoder.INSTANCE);
JsoniterSpi.registerTypeDecoder(com.alibaba.fastjson2.JSONArray.class, iter -> {
var any = iter.readAny();
if (any.valueType() == ValueType.NULL) {
return null;
} else if (any.valueType() == ValueType.ARRAY) {
return Fastjson2Library.getInstance().loads(any.toString());
}
throw new JsonException("type mismatch, expected ARRAY but was " + any.valueType());
});
}
}

private Fastjson2JSONArraySupport() {
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ public Any wrap(Object obj) {
throw new JsonException("type mismatch, expected ARRAY but was " + any.valueType());
};

/**
* Enable the {@code Jackson2JsonNodeSupport}.
*/
public static void enable() {
if (enabled.compareAndSet(false, true)) {
// register encoder for all nodes
Expand All @@ -152,6 +155,9 @@ public static void enable() {
}
}

private Jackson2JsonNodeSupport() {
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.util.OptionalInt;
import java.util.OptionalLong;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
Expand Down Expand Up @@ -229,4 +231,72 @@ public void testEncodeJsonNode() {
assertEquals("[1,2,3]", JsoniterLibrary.getInstance().dumpsToString(object.path("array")));
}

public static class TestFastjson2Objects {

private JSONObject obj;
private JSONArray arr;

public JSONObject getObj() {
return obj;
}

public void setObj(JSONObject obj) {
this.obj = obj;
}

public JSONArray getArr() {
return arr;
}

public void setArr(JSONArray arr) {
this.arr = arr;
}

}

@Test
public void testDecodeFastjson2() {
var test = JsoniterLibrary.getInstance().loads("""
{"obj":{"name":"test"},"arr":[1,2,3]}""", TestFastjson2Objects.class);
assertNotNull(test);
assertNotNull(test.obj);
assertEquals(1, test.obj.size());
assertEquals("test", test.obj.get("name"));
assertNotNull(test.arr);
assertEquals(3, test.arr.size());
assertEquals(1, test.arr.get(0));
assertEquals(2, test.arr.get(1));
assertEquals(3, test.arr.get(2));

test = JsoniterLibrary.getInstance().loads("{}", TestFastjson2Objects.class);
assertNotNull(test);
assertNull(test.obj);
assertNull(test.arr);
test = JsoniterLibrary.getInstance().loads("""
{"obj":null,"arr":null}""", TestFastjson2Objects.class);
assertNotNull(test);
assertNull(test.obj);
assertNull(test.arr);
}

@Test
public void testEncodeFastjson2() {
var object = new JSONObject();
object.fluentPut("int", 1)
.fluentPut("long", 1234567890123L)
.fluentPut("double", 1.2)
.fluentPut("boolean", true)
.fluentPut("string", "abc")
.fluentPut("bigInteger", new BigInteger("1234567890123456789012345"))
.fluentPut("bigDecimal", new BigDecimal("0.1234567890123456789012345"));
object.putObject("object").fluentPut("name", "test");
object.putArray("array").fluentAdd(1).fluentAdd(2).fluentAdd(3);
assertEquals(
Fastjson2Library.getInstance().dumpsToString(object),
JsoniterLibrary.getInstance().dumpsToString(object)
);
assertEquals("{\"name\":\"test\"}", JsoniterLibrary.getInstance().dumpsToString(object.get("object")));
assertEquals("[1,2,3]", JsoniterLibrary.getInstance().dumpsToString(object.get("array")));
}

}

0 comments on commit a9ee416

Please sign in to comment.