diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java index 7eddf3d988b..f9da1d2fbc0 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/JSON.java @@ -23,6 +23,8 @@ public interface JSON { boolean isSupport(); + boolean isJson(String json); + T toJavaObject(String json, Type type); List toJavaList(String json, Class clazz); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java index ef3e783a74e..ed0cca1d81a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJson2Impl.java @@ -19,9 +19,17 @@ import java.lang.reflect.Type; import java.util.List; +import com.alibaba.fastjson2.JSONValidator; import com.alibaba.fastjson2.JSONWriter; public class FastJson2Impl extends AbstractJSONImpl { + + @Override + public boolean isJson(String json) { + JSONValidator validator = JSONValidator.from(json); + return validator.validate(); + } + @Override public T toJavaObject(String json, Type type) { return com.alibaba.fastjson2.JSON.parseObject(json, type); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java index 97af77891f3..30d74d47a6f 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/FastJsonImpl.java @@ -23,6 +23,16 @@ public class FastJsonImpl extends AbstractJSONImpl { + @Override + public boolean isJson(String json) { + try { + Object obj = com.alibaba.fastjson.JSON.parse(json); + return obj instanceof com.alibaba.fastjson.JSONObject || obj instanceof com.alibaba.fastjson.JSONArray; + } catch (com.alibaba.fastjson.JSONException e) { + return false; + } + } + @Override public T toJavaObject(String json, Type type) { return com.alibaba.fastjson.JSON.parseObject(json, type); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java index cd4e53a7ad4..da79d9e91a3 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/GsonImpl.java @@ -20,12 +20,25 @@ import java.util.List; import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; public class GsonImpl extends AbstractJSONImpl { // weak reference of com.google.gson.Gson, prevent throw exception when init private volatile Object gsonCache = null; + @Override + public boolean isJson(String json) { + try { + JsonElement jsonElement = JsonParser.parseString(json); + return jsonElement.isJsonObject() || jsonElement.isJsonArray(); + } catch (JsonSyntaxException e) { + return false; + } + } + @Override public T toJavaObject(String json, Type type) { return getGson().fromJson(json, type); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/JacksonImpl.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/JacksonImpl.java index 28d822f8600..aff91726445 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/JacksonImpl.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/impl/JacksonImpl.java @@ -20,7 +20,9 @@ import java.util.List; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; @@ -31,6 +33,16 @@ public class JacksonImpl extends AbstractJSONImpl { private volatile Object jacksonCache = null; + @Override + public boolean isJson(String json) { + try { + JsonNode node = objectMapper.readTree(json); + return node.isObject() || node.isArray(); + } catch (JsonProcessingException e) { + return false; + } + } + @Override public T toJavaObject(String json, Type type) { try { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JsonUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JsonUtils.java index 0d259c6e51b..3ee05919d4c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JsonUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JsonUtils.java @@ -146,4 +146,8 @@ public static String getString(Map obj, String key) { public static List checkStringList(List rawList) { return getJson().checkStringList(rawList); } + + public static boolean checkJson(String json) { + return getJson().isJson(json); + } } diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java index 1b63d217d51..4d04e587413 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JsonUtilsTest.java @@ -63,6 +63,49 @@ void teardown() { } } + @Test + void testIsJson() { + JsonUtils.setJson(null); + // prefer use fastjson2 + System.setProperty("dubbo.json-framework.prefer", "fastjson2"); + Assertions.assertTrue( + JsonUtils.getJson().isJson("{\"title\":\"Java Programming\",\"author\":\"John Doe\",\"pages\":300}")); + Assertions.assertFalse(JsonUtils.getJson().isJson("This is not a JSON string")); + Assertions.assertTrue( + JsonUtils.getJson().isJson("[{\"title\":\"Java Programming\"}, {\"title\":\"Python Programming\"}]")); + System.clearProperty("dubbo.json-framework.prefer"); + + // prefer use fastjson + JsonUtils.setJson(null); + System.setProperty("dubbo.json-framework.prefer", "fastjson"); + Assertions.assertTrue( + JsonUtils.getJson().isJson("{\"title\":\"Java Programming\",\"author\":\"John Doe\",\"pages\":300}")); + Assertions.assertFalse(JsonUtils.getJson().isJson("This is not a JSON string")); + Assertions.assertTrue( + JsonUtils.getJson().isJson("[{\"title\":\"Java Programming\"}, {\"title\":\"Python Programming\"}]")); + System.clearProperty("dubbo.json-framework.prefer"); + + // prefer use gson + JsonUtils.setJson(null); + System.setProperty("dubbo.json-framework.prefer", "gson"); + Assertions.assertTrue( + JsonUtils.getJson().isJson("{\"title\":\"Java Programming\",\"author\":\"John Doe\",\"pages\":300}")); + Assertions.assertFalse(JsonUtils.getJson().isJson("This is not a JSON string")); + Assertions.assertTrue( + JsonUtils.getJson().isJson("[{\"title\":\"Java Programming\"}, {\"title\":\"Python Programming\"}]")); + System.clearProperty("dubbo.json-framework.prefer"); + + // prefer use jackson + JsonUtils.setJson(null); + System.setProperty("dubbo.json-framework.prefer", "jackson"); + Assertions.assertTrue( + JsonUtils.getJson().isJson("{\"title\":\"Java Programming\",\"author\":\"John Doe\",\"pages\":300}")); + Assertions.assertFalse(JsonUtils.getJson().isJson("This is not a JSON string")); + Assertions.assertTrue( + JsonUtils.getJson().isJson("[{\"title\":\"Java Programming\"}, {\"title\":\"Python Programming\"}]")); + System.clearProperty("dubbo.json-framework.prefer"); + } + @Test void testGetJson1() { Assertions.assertNotNull(JsonUtils.getJson()); diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java index 4052df8d262..e1eb953d72d 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java @@ -22,6 +22,7 @@ import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.ConcurrentHashMapUtils; import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.common.utils.JsonUtils; import org.apache.dubbo.common.utils.UrlUtils; import org.apache.dubbo.registry.NotifyListener; import org.apache.dubbo.registry.support.CacheableFailbackRegistry; @@ -46,6 +47,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.CHECK_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_ERROR_DESERIALIZE; import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_ZOOKEEPER_EXCEPTION; import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY; import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY; @@ -201,7 +203,15 @@ public void doSubscribe(final URL url, final NotifyListener listener) { ChildListener zkListener = ConcurrentHashMapUtils.computeIfAbsent( listeners, listener, k -> (parentPath, currentChildren) -> { for (String child : currentChildren) { - child = URL.decode(child); + try { + child = URL.decode(child); + if (!(JsonUtils.checkJson(child))) { + throw new Exception("dubbo-admin subscribe " + child + " failed,beacause " + + child + "is root path in " + url); + } + } catch (Exception e) { + logger.warn(PROTOCOL_ERROR_DESERIALIZE, "", "", e.getMessage()); + } if (!anyServices.contains(child)) { anyServices.add(child); subscribe(