Skip to content

Commit

Permalink
JsonUtils Support Fastjson2 (#10791)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlbumenJ authored Oct 29, 2022
1 parent c96a3a1 commit d78a5db
Show file tree
Hide file tree
Showing 8 changed files with 321 additions and 10 deletions.
5 changes: 5 additions & 0 deletions dubbo-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.json.impl;

import org.apache.dubbo.common.utils.ClassUtils;

import com.alibaba.fastjson2.JSONWriter;

import java.lang.reflect.Type;
import java.util.List;

public class FastJson2Impl extends AbstractJSONImpl {

@Override
public boolean isSupport() {
try {
Class<?> aClass = ClassUtils.forName("com.alibaba.fastjson2.JSON");
return aClass != null;
} catch (Throwable t) {
return false;
}
}

@Override
public <T> T toJavaObject(String json, Type type) {
return com.alibaba.fastjson2.JSON.parseObject(json, type);
}

@Override
public <T> List<T> toJavaList(String json, Class<T> clazz) {
return com.alibaba.fastjson2.JSON.parseArray(json, clazz);
}

@Override
public String toJson(Object obj) {
return com.alibaba.fastjson2.JSON.toJSONString(obj, JSONWriter.Feature.WriteEnumsUsingName);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.json.JSON;
import org.apache.dubbo.common.json.impl.FastJson2Impl;
import org.apache.dubbo.common.json.impl.FastJsonImpl;
import org.apache.dubbo.common.json.impl.GsonImpl;

Expand All @@ -36,6 +37,9 @@ public static JSON getJson() {
try {
JSON instance = null;
switch (preferJsonFrameworkName) {
case "fastjson2":
instance = new FastJson2Impl();
break;
case "fastjson":
instance = new FastJsonImpl();
break;
Expand All @@ -52,6 +56,7 @@ public static JSON getJson() {
}
if (json == null) {
List<Class<? extends JSON>> jsonClasses = Arrays.asList(
FastJson2Impl.class,
FastJsonImpl.class,
GsonImpl.class);
for (Class<? extends JSON> jsonClass : jsonClasses) {
Expand All @@ -67,7 +72,7 @@ public static JSON getJson() {
}
}
if (json == null) {
throw new IllegalStateException("Dubbo unable to find out any json framework (e.g. fastjson, gson) from jvm env. " +
throw new IllegalStateException("Dubbo unable to find out any json framework (e.g. fastjson2, fastjson, gson) from jvm env. " +
"Please import at least one json framework.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,20 @@
*/
package org.apache.dubbo.common.utils;

import org.apache.dubbo.common.json.impl.FastJson2Impl;
import org.apache.dubbo.common.json.impl.FastJsonImpl;
import org.apache.dubbo.common.json.impl.GsonImpl;
import org.apache.dubbo.common.utils.json.TestEnum;
import org.apache.dubbo.common.utils.json.TestObjectA;
import org.apache.dubbo.common.utils.json.TestObjectB;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
Expand All @@ -41,6 +46,14 @@ public void testGetJson1() {
Assertions.assertEquals(map, JsonUtils.getJson().toJavaObject("{\"a\":\"a\"}", Map.class));
Assertions.assertEquals(Collections.singletonList(map), JsonUtils.getJson().toJavaList("[{\"a\":\"a\"}]", Map.class));

// prefer use fastjson2
JsonUtils.setJson(null);
System.setProperty("dubbo.json-framework.prefer", "fastjson2");
Assertions.assertEquals("{\"a\":\"a\"}", JsonUtils.getJson().toJson(map));
Assertions.assertEquals(map, JsonUtils.getJson().toJavaObject("{\"a\":\"a\"}", Map.class));
Assertions.assertEquals(Collections.singletonList(map), JsonUtils.getJson().toJavaList("[{\"a\":\"a\"}]", Map.class));
System.clearProperty("dubbo.json-framework.prefer");

// prefer use fastjson
JsonUtils.setJson(null);
System.setProperty("dubbo.json-framework.prefer", "fastjson");
Expand All @@ -60,6 +73,94 @@ public void testGetJson1() {
JsonUtils.setJson(null);
}

@Test
public void consistentTest() {
List<Object> objs = new LinkedList<>();

{
objs.add(null);
}

{
Map<String, String> map = new HashMap<>();
map.put("a", "a");
objs.add(map);
}

{
TestObjectA a = new TestObjectA();
objs.add(a);
}

{
TestObjectA a = new TestObjectA();
a.setTestEnum(TestEnum.TYPE_A);
objs.add(a);
}

{
TestObjectB b = new TestObjectB();
objs.add(b);
}

{
TestObjectB b = new TestObjectB();
b.setInnerA(new TestObjectB.Inner());
b.setInnerB(new TestObjectB.Inner());
objs.add(b);
}

{
TestObjectB b = new TestObjectB();
TestObjectB.Inner inner1 = new TestObjectB.Inner();
TestObjectB.Inner inner2 = new TestObjectB.Inner();
inner1.setName("Test");
inner2.setName("Test");
b.setInnerA(inner1);
b.setInnerB(inner2);
objs.add(b);
}

{
TestObjectB b = new TestObjectB();
TestObjectB.Inner inner1 = new TestObjectB.Inner();
inner1.setName("Test");
b.setInnerA(inner1);
b.setInnerB(inner1);
objs.add(b);
}

for (Object obj : objs) {

// prefer use fastjson2
JsonUtils.setJson(null);
System.setProperty("dubbo.json-framework.prefer", "fastjson2");
Assertions.assertInstanceOf(FastJson2Impl.class, JsonUtils.getJson());
String fromFastjson2 = JsonUtils.getJson().toJson(obj);
System.clearProperty("dubbo.json-framework.prefer");

// prefer use fastjson
JsonUtils.setJson(null);
System.setProperty("dubbo.json-framework.prefer", "fastjson");
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
String fromFastjson1 = JsonUtils.getJson().toJson(obj);
System.clearProperty("dubbo.json-framework.prefer");

// prefer use gson
JsonUtils.setJson(null);
System.setProperty("dubbo.json-framework.prefer", "gson");
Assertions.assertInstanceOf(GsonImpl.class, JsonUtils.getJson());
String fromGson = JsonUtils.getJson().toJson(obj);
System.clearProperty("dubbo.json-framework.prefer");

JsonUtils.setJson(null);

Assertions.assertEquals(fromFastjson1, fromFastjson2);
Assertions.assertEquals(fromFastjson1, fromGson);
Assertions.assertEquals(fromFastjson2, fromGson);
}
}

@Test
public void testGetJson2() {
ClassLoader originClassLoader = Thread.currentThread().getContextClassLoader();
Expand All @@ -77,10 +178,17 @@ public Class<?> loadClass(String name) throws ClassNotFoundException {
};
Thread.currentThread().setContextClassLoader(newClassLoader);

// default use fastjson
// default use fastjson2
JsonUtils.setJson(null);
removedPackages.set(Collections.emptyList());
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
Assertions.assertInstanceOf(FastJson2Impl.class, JsonUtils.getJson());

// prefer use fastjson2
JsonUtils.setJson(null);
removedPackages.set(Collections.emptyList());
System.setProperty("dubbo.json-framework.prefer", "fastjson2");
Assertions.assertInstanceOf(FastJson2Impl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");

// prefer use fastjson
JsonUtils.setJson(null);
Expand All @@ -100,36 +208,48 @@ public Class<?> loadClass(String name) throws ClassNotFoundException {
JsonUtils.setJson(null);
removedPackages.set(Collections.emptyList());
System.setProperty("dubbo.json-framework.prefer", "notfound");
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
Assertions.assertInstanceOf(FastJson2Impl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");

JsonUtils.setJson(null);
// TCCL not found fastjson2
removedPackages.set(Collections.singletonList("com.alibaba.fastjson2"));
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());

JsonUtils.setJson(null);
// TCCL not found fastjson
removedPackages.set(Collections.singletonList("com.alibaba.fastjson"));
removedPackages.set(Arrays.asList("com.alibaba.fastjson2", "com.alibaba.fastjson"));
Assertions.assertInstanceOf(GsonImpl.class, JsonUtils.getJson());

JsonUtils.setJson(null);
// TCCL not found gson
removedPackages.set(Collections.singletonList("com.google.gson"));
removedPackages.set(Arrays.asList("com.alibaba.fastjson2", "com.google.gson"));
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());

JsonUtils.setJson(null);
// TCCL not found fastjson2, prefer use fastjson
removedPackages.set(Collections.singletonList("com.alibaba.fastjson2"));
System.setProperty("dubbo.json-framework.prefer", "fastjson");
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");

JsonUtils.setJson(null);
// TCCL not found fastjson, prefer use fastjson
removedPackages.set(Collections.singletonList("com.alibaba.fastjson"));
removedPackages.set(Arrays.asList("com.alibaba.fastjson2", "com.alibaba.fastjson"));
System.setProperty("dubbo.json-framework.prefer", "fastjson");
Assertions.assertInstanceOf(GsonImpl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");

JsonUtils.setJson(null);
// TCCL not found gson, prefer use gson
removedPackages.set(Collections.singletonList("com.google.gson"));
removedPackages.set(Arrays.asList("com.alibaba.fastjson2", "com.google.gson"));
System.setProperty("dubbo.json-framework.prefer", "gson");
Assertions.assertInstanceOf(FastJsonImpl.class, JsonUtils.getJson());
System.clearProperty("dubbo.json-framework.prefer");

JsonUtils.setJson(null);
// TCCL not found fastjson, gson
removedPackages.set(Arrays.asList("com.alibaba.fastjson", "com.google.gson"));
removedPackages.set(Arrays.asList("com.alibaba.fastjson2", "com.alibaba.fastjson", "com.google.gson"));
Assertions.assertThrows(IllegalStateException.class, JsonUtils::getJson);

Thread.currentThread().setContextClassLoader(originClassLoader);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.utils.json;

public enum TestEnum {
TYPE_A, TYPE_B, TYPE_C
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.utils.json;

public class TestObjectA {
private String name;
private int age;
private TestEnum testEnum;

public TestObjectA() {
}

public TestObjectA(String name, int age, TestEnum testEnum) {
this.name = name;
this.age = age;
this.testEnum = testEnum;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public TestEnum getTestEnum() {
return testEnum;
}

public void setTestEnum(TestEnum testEnum) {
this.testEnum = testEnum;
}
}
Loading

0 comments on commit d78a5db

Please sign in to comment.