diff --git a/CHANGELOG.md b/CHANGELOG.md index e964fcdac..3a7290ce3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ ## 5.0.1 ### 新特性 +* 【json】 JSONUtil.toBean支持JSONArray ### Bug修复 +* 【extra】 修复getSession端口判断错误 ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ssh/JschUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/ssh/JschUtil.java index ec10f4d6b..63c4bb6a2 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/ssh/JschUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/ssh/JschUtil.java @@ -157,7 +157,7 @@ public class JschUtil { */ public static Session createSession(String sshHost, int sshPort, String sshUser, String privateKeyPath, byte[] passphrase) { Assert.notEmpty(sshHost, "SSH Host must be not empty!"); - Assert.isTrue(sshPort < 0, "SSH Host must be not empty!"); + Assert.isTrue(sshPort > 0, "SSH port must be > 0"); Assert.notEmpty(privateKeyPath, "PrivateKey Path must be not empty!"); // 默认root用户 diff --git a/hutool-extra/src/test/java/cn/hutool/extra/ssh/JschUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/ssh/JschUtilTest.java index 5c57880c8..444f77c6f 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/ssh/JschUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/ssh/JschUtilTest.java @@ -1,5 +1,6 @@ package cn.hutool.extra.ssh; +import com.jcraft.jsch.JSch; import org.junit.Ignore; import org.junit.Test; @@ -61,4 +62,9 @@ public class JschUtilTest { IoUtil.close(sftp); } + + @Test + public void getSessionTest(){ + JschUtil.getSession("192.168.1.134", 22, "root", "aaa", null); + } } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSON.java b/hutool-json/src/main/java/cn/hutool/json/JSON.java index ca71ebd36..cdbe26e6f 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSON.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSON.java @@ -1,17 +1,19 @@ package cn.hutool.json; import java.io.Serializable; +import java.io.StringWriter; import java.io.Writer; +import java.lang.reflect.Type; import cn.hutool.core.bean.BeanPath; +import cn.hutool.core.lang.TypeReference; /** * JSON接口 - * - * @author Looly * + * @author Looly */ -public interface JSON extends Cloneable, Serializable{ +public interface JSON extends Cloneable, Serializable { /** * 通过表达式获取JSON中嵌套的对象
@@ -19,16 +21,16 @@ public interface JSON extends Cloneable, Serializable{ *
  • .表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值
  • *
  • []表达式,可以获取集合等对象中对应index的值
  • * - * + *

    * 表达式栗子: - * + * *

     	 * persion
     	 * persion.name
     	 * persons[3]
     	 * person.friends[5].name
     	 * 
    - * + * * @param expression 表达式 * @return 对象 * @see BeanPath#get(Object) @@ -44,20 +46,20 @@ public interface JSON extends Cloneable, Serializable{ *
  • .表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值
  • *
  • []表达式,可以获取集合等对象中对应index的值
  • * - * + *

    * 表达式栗子: - * + * *

     	 * persion
     	 * persion.name
     	 * persons[3]
     	 * person.friends[5].name
     	 * 
    - * + * * @param expression 表达式 - * @param value 值 + * @param value 值 */ - public void putByPath(String expression, Object value); + void putByPath(String expression, Object value); /** * 通过表达式获取JSON中嵌套的对象
    @@ -65,19 +67,19 @@ public interface JSON extends Cloneable, Serializable{ *
  • .表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值
  • *
  • []表达式,可以获取集合等对象中对应index的值
  • * - * + *

    * 表达式栗子: - * + * *

     	 * persion
     	 * persion.name
     	 * persons[3]
     	 * person.friends[5].name
     	 * 
    - * + *

    * 获取表达式对应值后转换为对应类型的值 - * - * @param 返回值类型 + * + * @param 返回值类型 * @param expression 表达式 * @param resultType 返回值类型 * @return 对象 @@ -86,43 +88,100 @@ public interface JSON extends Cloneable, Serializable{ */ T getByPath(String expression, Class resultType); + /** + * 格式化打印JSON,缩进为4个空格 + * + * @return 格式化后的JSON字符串 + * @throws JSONException 包含非法数抛出此异常 + * @since 3.0.9 + */ + default String toStringPretty() throws JSONException { + return this.toJSONString(4); + } + + /** + * 格式化输出JSON字符串 + * + * @param indentFactor 每层缩进空格数 + * @return JSON字符串 + * @throws JSONException 包含非法数抛出此异常 + */ + default String toJSONString(int indentFactor) throws JSONException { + final StringWriter sw = new StringWriter(); + synchronized (sw.getBuffer()) { + return this.write(sw, indentFactor, 0).toString(); + } + } + /** * 将JSON内容写入Writer,无缩进
    * Warning: This method assumes that the data structure is acyclical. - * + * * @param writer Writer * @return Writer * @throws JSONException JSON相关异常 */ - Writer write(Writer writer) throws JSONException; + default Writer write(Writer writer) throws JSONException { + return this.write(writer, 0, 0); + } /** * 将JSON内容写入Writer
    * Warning: This method assumes that the data structure is acyclical. - * - * @param writer writer + * + * @param writer writer * @param indentFactor 缩进因子,定义每一级别增加的缩进量 - * @param indent 本级别缩进量 + * @param indent 本级别缩进量 * @return Writer * @throws JSONException JSON相关异常 */ Writer write(Writer writer, int indentFactor, int indent) throws JSONException; /** - * 转换为JSON字符串 - * - * @param indentFactor 缩进因子,定义每一级别增加的缩进量 - * @return JSON字符串 - * @throws JSONException JSON相关异常 + * 转为实体类对象,转换异常将被抛出 + * + * @param Bean类型 + * @param clazz 实体类 + * @return 实体类对象 */ - String toJSONString(int indentFactor) throws JSONException; + default T toBean(Class clazz) { + return toBean((Type) clazz); + } /** - * 格式化打印JSON,缩进为4个空格 - * - * @return 格式化后的JSON字符串 - * @throws JSONException 包含非法数抛出此异常 - * @since 3.0.9 + * 转为实体类对象,转换异常将被抛出 + * + * @param Bean类型 + * @param reference {@link TypeReference}类型参考子类,可以获取其泛型参数中的Type类型 + * @return 实体类对象 + * @since 4.2.2 */ - String toStringPretty() throws JSONException; + default T toBean(TypeReference reference) { + return toBean(reference.getType()); + } + + /** + * 转为实体类对象 + * + * @param Bean类型 + * @param type {@link Type} + * @return 实体类对象 + * @since 3.0.8 + */ + default T toBean(Type type) { + return toBean(type, false); + } + + /** + * 转为实体类对象 + * + * @param Bean类型 + * @param type {@link Type} + * @param ignoreError 是否忽略转换错误 + * @return 实体类对象 + * @since 4.3.2 + */ + default T toBean(Type type, boolean ignoreError) { + return JSONConverter.jsonConvert(type, this, ignoreError); + } } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java index 6c1198db2..49610bc68 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java @@ -1,15 +1,5 @@ package cn.hutool.json; -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.RandomAccess; - import cn.hutool.core.bean.BeanPath; import cn.hutool.core.collection.ArrayIter; import cn.hutool.core.collection.CollUtil; @@ -20,6 +10,15 @@ import cn.hutool.core.util.TypeUtil; import cn.hutool.json.serialize.GlobalSerializeMapping; import cn.hutool.json.serialize.JSONSerializer; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; + /** * JSON数组
    * JSON数组是表示中括号括住的数据表现形式
    @@ -498,38 +497,6 @@ public class JSONArray extends JSONGetter implements JSON, List } } - /** - * 格式化打印JSON,缩进为4个空格 - * - * @return 格式化后的JSON字符串 - * @throws JSONException 包含非法数抛出此异常 - * @since 3.0.9 - */ - @Override - public String toStringPretty() throws JSONException { - return this.toJSONString(4); - } - - /** - * 转为JSON字符串,指定缩进值 - * - * @param indentFactor 缩进值,即缩进空格数 - * @return JSON字符串 - * @throws JSONException JSON写入异常 - */ - @Override - public String toJSONString(int indentFactor) throws JSONException { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - return this.write(sw, indentFactor, 0).toString(); - } - } - - @Override - public Writer write(Writer writer) throws JSONException { - return this.write(writer, 0, 0); - } - @Override public Writer write(Writer writer, int indentFactor, int indent) throws JSONException { try { diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java b/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java index ce7909ae8..f51623b2d 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONConverter.java @@ -77,7 +77,7 @@ public class JSONConverter implements Converter { } } - Object targetValue = null; + Object targetValue; try { targetValue = Convert.convert(targetType, value); } catch (ConvertException e) { diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java index accc350b5..13bcb8d7d 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java @@ -1,24 +1,10 @@ package cn.hutool.json; -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - import cn.hutool.core.bean.BeanDesc.PropDesc; import cn.hutool.core.bean.BeanPath; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; -import cn.hutool.core.lang.TypeReference; import cn.hutool.core.map.CaseInsensitiveLinkedMap; import cn.hutool.core.map.CaseInsensitiveMap; import cn.hutool.core.util.ArrayUtil; @@ -30,6 +16,18 @@ import cn.hutool.json.serialize.GlobalSerializeMapping; import cn.hutool.json.serialize.JSONObjectSerializer; import cn.hutool.json.serialize.JSONSerializer; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + /** * JSON对象
    * 例:
    @@ -111,9 +109,9 @@ public class JSONObject extends JSONGetter implements JSON, Map(capacity) : new CaseInsensitiveMap(capacity); + this.rawHashMap = config.isOrder() ? new CaseInsensitiveLinkedMap<>(capacity) : new CaseInsensitiveMap<>(capacity); } else { - this.rawHashMap = config.isOrder() ? new LinkedHashMap(capacity) : new HashMap(capacity); + this.rawHashMap = config.isOrder() ? new LinkedHashMap<>(capacity) : new HashMap<>(capacity); } this.config = config; } @@ -288,54 +286,6 @@ public class JSONObject extends JSONGetter implements JSON, Map Bean类型 - * @param clazz 实体类 - * @return 实体类对象 - */ - public T toBean(Class clazz) { - return toBean((Type) clazz); - } - - /** - * 转为实体类对象,转换异常将被抛出 - * - * @param Bean类型 - * @param reference {@link TypeReference}类型参考子类,可以获取其泛型参数中的Type类型 - * @return 实体类对象 - * @since 4.2.2 - */ - public T toBean(TypeReference reference) { - return toBean(reference.getType()); - } - - /** - * 转为实体类对象 - * - * @param Bean类型 - * @param type {@link Type} - * @return 实体类对象 - * @since 3.0.8 - */ - public T toBean(Type type) { - return toBean(type, false); - } - - /** - * 转为实体类对象 - * - * @param Bean类型 - * @param type {@link Type} - * @param ignoreError 是否忽略转换错误 - * @return 实体类对象 - * @since 4.3.2 - */ - public T toBean(Type type, boolean ignoreError) { - return JSONConverter.jsonConvert(type, this, ignoreError); - } - @Override public int size() { return rawHashMap.size(); @@ -586,36 +536,6 @@ public class JSONObject extends JSONGetter implements JSON, Map T toBean(String jsonString, Type beanType, boolean ignoreError) { - return toBean(parseObj(jsonString), beanType, ignoreError); + return toBean(parse(jsonString), beanType, ignoreError); } /** @@ -391,7 +391,7 @@ public final class JSONUtil { * @return 实体类对象 * @since 4.6.2 */ - public static T toBean(JSONObject json, TypeReference typeReference, boolean ignoreError) { + public static T toBean(JSON json, TypeReference typeReference, boolean ignoreError) { return toBean(json, typeReference.getType(), ignoreError); } @@ -405,7 +405,7 @@ public final class JSONUtil { * @return 实体类对象 * @since 4.3.2 */ - public static T toBean(JSONObject json, Type beanType, boolean ignoreError) { + public static T toBean(JSON json, Type beanType, boolean ignoreError) { if (null == json) { return null; } diff --git a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONArraySerializer.java b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONArraySerializer.java index 7a4047f6a..23db69e28 100644 --- a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONArraySerializer.java +++ b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONArraySerializer.java @@ -9,4 +9,5 @@ import cn.hutool.json.JSONArray; * * @author Looly */ +@FunctionalInterface public interface JSONArraySerializer extends JSONSerializer{} diff --git a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONDeserializer.java b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONDeserializer.java index 69122c9eb..de6d88a59 100644 --- a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONDeserializer.java +++ b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONDeserializer.java @@ -9,6 +9,7 @@ import cn.hutool.json.JSON; * * @param 反序列化后的类型 */ +@FunctionalInterface public interface JSONDeserializer { /** diff --git a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONObjectSerializer.java b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONObjectSerializer.java index cc22efa71..dc0817f13 100644 --- a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONObjectSerializer.java +++ b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONObjectSerializer.java @@ -8,4 +8,5 @@ import cn.hutool.json.JSONObject; * * @author Looly */ +@FunctionalInterface public interface JSONObjectSerializer extends JSONSerializer{} diff --git a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONSerializer.java b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONSerializer.java index e626d4e4f..ca8fc5516 100644 --- a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONSerializer.java +++ b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONSerializer.java @@ -9,6 +9,7 @@ import cn.hutool.json.JSON; * @param 对象类型 * @author Looly */ +@FunctionalInterface public interface JSONSerializer { /** diff --git a/hutool-json/src/test/java/cn/hutool/json/CustomSerializeTest.java b/hutool-json/src/test/java/cn/hutool/json/CustomSerializeTest.java index 10cd7ba49..5ebe9f333 100644 --- a/hutool-json/src/test/java/cn/hutool/json/CustomSerializeTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/CustomSerializeTest.java @@ -1,25 +1,17 @@ package cn.hutool.json; -import java.util.Date; - +import cn.hutool.json.serialize.JSONObjectSerializer; +import lombok.ToString; import org.junit.Assert; import org.junit.Test; -import cn.hutool.json.serialize.JSONDeserializer; -import cn.hutool.json.serialize.JSONObjectSerializer; -import lombok.ToString; +import java.util.Date; public class CustomSerializeTest { @Test public void serializeTest() { - JSONUtil.putSerializer(CustomBean.class, new JSONObjectSerializer() { - - @Override - public void serialize(JSONObject json, CustomBean bean) { - json.put("customName", bean.name); - } - }); + JSONUtil.putSerializer(CustomBean.class, (JSONObjectSerializer) (json, bean) -> json.put("customName", bean.name)); CustomBean customBean = new CustomBean(); customBean.name = "testName"; @@ -30,15 +22,10 @@ public class CustomSerializeTest { @Test public void deserializeTest() { - JSONUtil.putDeserializer(CustomBean.class, new JSONDeserializer() { - - @Override - public CustomBean deserialize(JSON json) { - CustomBean customBean = new CustomBean(); - customBean.name = ((JSONObject)json).getStr("customName"); - return customBean; - } - + JSONUtil.putDeserializer(CustomBean.class, json -> { + CustomBean customBean = new CustomBean(); + customBean.name = ((JSONObject)json).getStr("customName"); + return customBean; }); String jsonStr = "{\"customName\":\"testName\"}"; diff --git a/hutool-json/src/test/java/cn/hutool/json/Issue488Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue488Test.java index 78887a4f8..99b012288 100644 --- a/hutool-json/src/test/java/cn/hutool/json/Issue488Test.java +++ b/hutool-json/src/test/java/cn/hutool/json/Issue488Test.java @@ -31,14 +31,36 @@ public class Issue488Test { Assert.assertEquals("MeetingRoom219@abc.com", adds.get(3).getAddress()); } + @Test + public void toCollctionBeanTest() { + String jsonStr = ResourceUtil.readUtf8Str("issue488Array.json"); + + List>> resultList = JSONUtil.toBean(jsonStr, + new TypeReference>>>() {}, false); + + ResultSuccess> result = resultList.get(0); + + Assert.assertEquals("https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.emailAddress)", result.getContext()); + + List adds = result.getValue(); + Assert.assertEquals("会议室101", adds.get(0).getName()); + Assert.assertEquals("MeetingRoom101@abc.com", adds.get(0).getAddress()); + Assert.assertEquals("会议室102", adds.get(1).getName()); + Assert.assertEquals("MeetingRoom102@abc.com", adds.get(1).getAddress()); + Assert.assertEquals("会议室103", adds.get(2).getName()); + Assert.assertEquals("MeetingRoom103@abc.com", adds.get(2).getAddress()); + Assert.assertEquals("会议室219", adds.get(3).getName()); + Assert.assertEquals("MeetingRoom219@abc.com", adds.get(3).getAddress()); + } + @Data - public class ResultSuccess { + public static class ResultSuccess { private String context; private T value; } @Data - public class EmailAddress { + public static class EmailAddress { private String name; private String address; } diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONConvertTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONConvertTest.java index 9cc8276e9..844784a76 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONConvertTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONConvertTest.java @@ -1,20 +1,17 @@ package cn.hutool.json; +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.json.test.bean.ExamInfoDict; +import cn.hutool.json.test.bean.PerfectEvaluationProductResVo; +import cn.hutool.json.test.bean.UserInfoDict; +import org.junit.Assert; +import org.junit.Test; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.junit.Assert; -import org.junit.Test; - -import cn.hutool.core.io.resource.ResourceUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import cn.hutool.json.test.bean.ExamInfoDict; -import cn.hutool.json.test.bean.PerfectEvaluationProductResVo; -import cn.hutool.json.test.bean.UserInfoDict; - /** * JSON转换单元测试 * @@ -46,14 +43,14 @@ public class JSONConvertTest { examInfoDict2.setExamType(1); examInfoDict2.setAnswerIs(0); - List examInfoDicts = new ArrayList(); + List examInfoDicts = new ArrayList<>(); examInfoDicts.add(examInfoDict); examInfoDicts.add(examInfoDict1); examInfoDicts.add(examInfoDict2); userInfoDict.setExamInfoDict(examInfoDicts); - Map tempMap = new HashMap(); + Map tempMap = new HashMap<>(); tempMap.put("userInfoDict", userInfoDict); tempMap.put("toSendManIdCard", 1); diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java index 7c270f1a3..d5db03c2b 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java @@ -161,7 +161,7 @@ public class JSONObjectTest { // 当JSON中为字符串"null"时应被当作字符串处理 Assert.assertEquals("null", bean.getStrValue()); // 当JSON中为字符串"null"时Bean中的字段类型不匹配应在ignoreError模式下忽略注入 - Assert.assertEquals(null, bean.getBeanValue()); + Assert.assertNull(bean.getBeanValue()); } @Test diff --git a/hutool-json/src/test/resources/issue488Array.json b/hutool-json/src/test/resources/issue488Array.json new file mode 100644 index 000000000..e0c6d0588 --- /dev/null +++ b/hutool-json/src/test/resources/issue488Array.json @@ -0,0 +1,16 @@ +[{ + "context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.emailAddress)", + "value": [{ + "name": "\u4f1a\u8bae\u5ba4101", + "address": "MeetingRoom101@abc.com" + }, { + "name": "\u4f1a\u8bae\u5ba4102", + "address": "MeetingRoom102@abc.com" + }, { + "name": "\u4f1a\u8bae\u5ba4103", + "address": "MeetingRoom103@abc.com" + }, { + "name": "\u4f1a\u8bae\u5ba4219", + "address": "MeetingRoom219@abc.com" + }] +}] \ No newline at end of file