Looly 5 年 前
コミット
65552f4f54
19 ファイル変更398 行追加59 行削除
  1. 3 1
      CHANGELOG.md
  2. 8 0
      hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java
  3. 22 0
      hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicIntegerArrayConverter.java
  4. 22 0
      hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicLongArrayConverter.java
  5. 23 25
      hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java
  6. 62 3
      hutool-core/src/main/java/cn/hutool/core/convert/impl/StringConverter.java
  7. 43 0
      hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
  8. 44 4
      hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java
  9. 16 0
      hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java
  10. 15 0
      hutool-core/src/test/java/cn/hutool/core/convert/StringConvertTest.java
  11. BIN
      hutool-extra/bopomofo4j-temp/bopomofo4j-c6e41074-5302-42b6-9bdf-8742cb416a62.jar
  12. 6 0
      hutool-extra/pom.xml
  13. 43 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/Bopomofo4jEngine.java
  14. 20 0
      hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/package-info.java
  15. 2 1
      hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.pinyin.PinyinEngine
  16. 15 0
      hutool-extra/src/test/java/cn/hutool/extra/pinyin/PinyinUtilTest.java
  17. 4 0
      hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java
  18. 27 25
      hutool-json/src/main/java/cn/hutool/json/JSONObject.java
  19. 23 0
      hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java

+ 3 - 1
CHANGELOG.md

@@ -3,7 +3,7 @@
 
 -------------------------------------------------------------------------------------------------------------
 
-# 5.4.5 (2020-10-16)
+# 5.4.5 (2020-10-17)
 
 ### 新特性
 * 【core   】     ConsoleTable代码优化(pr#190@Gitee)
@@ -20,6 +20,8 @@
 * 【core   】     优化针对list的split方法(pr#194@Gitee)
 * 【poi    】     ExcelWriter增加setRowStyle方法
 * 【core   】     Assert增加函数接口(pr#1166@Github)
+* 【core   】     新增AtomicIntegerArray、AtomicLongArray转换
+* 【extra  】     PinyinUtil新增Bopomofo4j支持
 
 ### Bug修复
 * 【core   】     解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee)

+ 8 - 0
hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java

@@ -3,6 +3,8 @@ package cn.hutool.core.convert;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.convert.impl.ArrayConverter;
 import cn.hutool.core.convert.impl.AtomicBooleanConverter;
+import cn.hutool.core.convert.impl.AtomicIntegerArrayConverter;
+import cn.hutool.core.convert.impl.AtomicLongArrayConverter;
 import cn.hutool.core.convert.impl.AtomicReferenceConverter;
 import cn.hutool.core.convert.impl.BeanConverter;
 import cn.hutool.core.convert.impl.BooleanConverter;
@@ -69,7 +71,9 @@ import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicIntegerArray;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicLongArray;
 import java.util.concurrent.atomic.AtomicReference;
 
 /**
@@ -423,6 +427,10 @@ public class ConverterRegistry implements Serializable {
 		defaultConverterMap.put(SoftReference.class, new ReferenceConverter(SoftReference.class));// since 3.0.8
 		defaultConverterMap.put(AtomicReference.class, new AtomicReferenceConverter());// since 3.0.8
 
+		//AtomicXXXArray,since 5.4.5
+		defaultConverterMap.put(AtomicIntegerArray.class, new AtomicIntegerArrayConverter());
+		defaultConverterMap.put(AtomicLongArray.class, new AtomicLongArrayConverter());
+
 		// 其它类型
 		defaultConverterMap.put(Class.class, new ClassConverter());
 		defaultConverterMap.put(TimeZone.class, new TimeZoneConverter());

+ 22 - 0
hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicIntegerArrayConverter.java

@@ -0,0 +1,22 @@
+package cn.hutool.core.convert.impl;
+
+import cn.hutool.core.convert.AbstractConverter;
+import cn.hutool.core.convert.Convert;
+
+import java.util.concurrent.atomic.AtomicIntegerArray;
+
+/**
+ * {@link AtomicIntegerArray}转换器
+ * 
+ * @author Looly
+ * @since 5.4.5
+ */
+public class AtomicIntegerArrayConverter extends AbstractConverter<AtomicIntegerArray> {
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	protected AtomicIntegerArray convertInternal(Object value) {
+		return new AtomicIntegerArray(Convert.convert(int[].class, value));
+	}
+
+}

+ 22 - 0
hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicLongArrayConverter.java

@@ -0,0 +1,22 @@
+package cn.hutool.core.convert.impl;
+
+import cn.hutool.core.convert.AbstractConverter;
+import cn.hutool.core.convert.Convert;
+
+import java.util.concurrent.atomic.AtomicLongArray;
+
+/**
+ * {@link AtomicLongArray}转换器
+ * 
+ * @author Looly
+ * @since 5.4.5
+ */
+public class AtomicLongArrayConverter extends AbstractConverter<AtomicLongArray> {
+	private static final long serialVersionUID = 1L;
+
+	@Override
+	protected AtomicLongArray convertInternal(Object value) {
+		return new AtomicLongArray(Convert.convert(long[].class, value));
+	}
+
+}

+ 23 - 25
hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java

@@ -13,6 +13,8 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.DoubleAdder;
+import java.util.concurrent.atomic.LongAdder;
 
 /**
  * 数字转换器<br>
@@ -64,7 +66,6 @@ public class NumberConverter extends AbstractConverter<Number> {
 			}
 			final String valueStr = convertToStr(value);
 			return StrUtil.isBlank(valueStr) ? null : Byte.valueOf(valueStr);
-
 		} else if (Short.class == targetType) {
 			if (value instanceof Number) {
 				return ((Number) value).shortValue();
@@ -73,7 +74,6 @@ public class NumberConverter extends AbstractConverter<Number> {
 			}
 			final String valueStr = convertToStr(value);
 			return StrUtil.isBlank(valueStr) ? null : Short.valueOf(valueStr);
-
 		} else if (Integer.class == targetType) {
 			if (value instanceof Number) {
 				return ((Number) value).intValue();
@@ -88,7 +88,6 @@ public class NumberConverter extends AbstractConverter<Number> {
 			}
 			final String valueStr = convertToStr(value);
 			return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseInt(valueStr);
-
 		} else if (AtomicInteger.class == targetType) {
 			final Number number = convertInternal(value, Integer.class);
 			if (null != number) {
@@ -96,7 +95,6 @@ public class NumberConverter extends AbstractConverter<Number> {
 				intValue.set(number.intValue());
 				return intValue;
 			}
-			return null;
 		} else if (Long.class == targetType) {
 			if (value instanceof Number) {
 				return ((Number) value).longValue();
@@ -111,7 +109,6 @@ public class NumberConverter extends AbstractConverter<Number> {
 			}
 			final String valueStr = convertToStr(value);
 			return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseLong(valueStr);
-
 		} else if (AtomicLong.class == targetType) {
 			final Number number = convertInternal(value, Long.class);
 			if (null != number) {
@@ -119,7 +116,14 @@ public class NumberConverter extends AbstractConverter<Number> {
 				longValue.set(number.longValue());
 				return longValue;
 			}
-			return null;
+		}else if (LongAdder.class == targetType) {
+			//jdk8 新增
+			final Number number = convertInternal(value, Long.class);
+			if (null != number) {
+				final LongAdder longValue = new LongAdder();
+				longValue.add(number.longValue());
+				return longValue;
+			}
 		} else if (Float.class == targetType) {
 			if (value instanceof Number) {
 				return ((Number) value).floatValue();
@@ -137,13 +141,18 @@ public class NumberConverter extends AbstractConverter<Number> {
 			}
 			final String valueStr = convertToStr(value);
 			return StrUtil.isBlank(valueStr) ? null : Double.valueOf(valueStr);
-
+		}else if (DoubleAdder.class == targetType) {
+			//jdk8 新增
+			final Number number = convertInternal(value, Long.class);
+			if (null != number) {
+				final DoubleAdder doubleAdder = new DoubleAdder();
+				doubleAdder.add(number.doubleValue());
+				return doubleAdder;
+			}
 		} else if (BigDecimal.class == targetType) {
 			return toBigDecimal(value);
-
 		} else if (BigInteger.class == targetType) {
 			return toBigInteger(value);
-
 		} else if (Number.class == targetType) {
 			if (value instanceof Number) {
 				return (Number) value;
@@ -166,22 +175,14 @@ public class NumberConverter extends AbstractConverter<Number> {
 	 * @return 结果
 	 */
 	private BigDecimal toBigDecimal(Object value) {
-		if (value instanceof Long) {
-			return new BigDecimal((Long) value);
-		} else if (value instanceof Integer) {
-			return new BigDecimal((Integer) value);
-		} else if (value instanceof BigInteger) {
-			return new BigDecimal((BigInteger) value);
+		if (value instanceof Number) {
+			return NumberUtil.toBigDecimal((Number) value);
 		} else if (value instanceof Boolean) {
 			return new BigDecimal((boolean) value ? 1 : 0);
 		}
 
 		//对于Double类型,先要转换为String,避免精度问题
-		final String valueStr = convertToStr(value);
-		if (StrUtil.isBlank(valueStr)) {
-			return null;
-		}
-		return new BigDecimal(valueStr);
+		return NumberUtil.toBigDecimal(convertToStr(value));
 	}
 
 	/**
@@ -198,11 +199,8 @@ public class NumberConverter extends AbstractConverter<Number> {
 		} else if (value instanceof Boolean) {
 			return BigInteger.valueOf((boolean) value ? 1 : 0);
 		}
-		final String valueStr = convertToStr(value);
-		if (StrUtil.isBlank(valueStr)) {
-			return null;
-		}
-		return new BigInteger(valueStr);
+
+		return NumberUtil.toBigInteger(convertToStr(value));
 	}
 
 	@Override

+ 62 - 3
hutool-core/src/main/java/cn/hutool/core/convert/impl/StringConverter.java

@@ -1,18 +1,77 @@
 package cn.hutool.core.convert.impl;
 
 import cn.hutool.core.convert.AbstractConverter;
+import cn.hutool.core.convert.ConvertException;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.XmlUtil;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.SQLException;
+import java.util.TimeZone;
 
 /**
- * 字符串转换器
- * @author Looly
+ * 字符串转换器,提供各种对象转换为字符串的逻辑封装
  *
+ * @author Looly
  */
-public class StringConverter extends AbstractConverter<String>{
+public class StringConverter extends AbstractConverter<String> {
 	private static final long serialVersionUID = 1L;
 
 	@Override
 	protected String convertInternal(Object value) {
+		if (value instanceof TimeZone) {
+			return ((TimeZone) value).getID();
+		} else if (value instanceof org.w3c.dom.Node) {
+			return XmlUtil.toStr((org.w3c.dom.Node) value);
+		} else if (value instanceof Clob) {
+			return clobToStr((Clob) value);
+		} else if (value instanceof Blob) {
+			return blobToStr((Blob) value);
+		}
+
+		// 其它情况
 		return convertToStr(value);
 	}
 
+	/**
+	 * Clob字段值转字符串
+	 *
+	 * @param clob {@link Clob}
+	 * @return 字符串
+	 * @since 5.4.5
+	 */
+	private static String clobToStr(Clob clob) {
+		Reader reader = null;
+		try {
+			reader = clob.getCharacterStream();
+			return IoUtil.read(reader);
+		} catch (SQLException e) {
+			throw new ConvertException(e);
+		} finally {
+			IoUtil.close(reader);
+		}
+	}
+
+	/**
+	 * Blob字段值转字符串
+	 *
+	 * @param blob    {@link Blob}
+	 * @return 字符串
+	 * @since 5.4.5
+	 */
+	private static String blobToStr(Blob blob) {
+		InputStream in = null;
+		try {
+			in = blob.getBinaryStream();
+			return IoUtil.read(in, CharsetUtil.CHARSET_UTF_8);
+		} catch (SQLException e) {
+			throw new ConvertException(e);
+		} finally {
+			IoUtil.close(in);
+		}
+	}
 }

+ 43 - 0
hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java

@@ -2005,6 +2005,17 @@ public class NumberUtil {
 		if (null == number) {
 			return BigDecimal.ZERO;
 		}
+
+		if(number instanceof BigDecimal){
+			return (BigDecimal) number;
+		} else if (number instanceof Long) {
+			return new BigDecimal((Long) number);
+		} else if (number instanceof Integer) {
+			return new BigDecimal((Integer) number);
+		} else if (number instanceof BigInteger) {
+			return new BigDecimal((BigInteger) number);
+		}
+
 		return toBigDecimal(number.toString());
 	}
 
@@ -2020,6 +2031,38 @@ public class NumberUtil {
 	}
 
 	/**
+	 * 数字转{@link BigInteger}
+	 *
+	 * @param number 数字
+	 * @return {@link BigInteger}
+	 * @since 5.4.5
+	 */
+	public static BigInteger toBigInteger(Number number) {
+		if (null == number) {
+			return BigInteger.ZERO;
+		}
+
+		if(number instanceof BigInteger){
+			return (BigInteger) number;
+		} else if (number instanceof Long) {
+			return BigInteger.valueOf((Long) number);
+		}
+
+		return toBigInteger(number.longValue());
+	}
+
+	/**
+	 * 数字转{@link BigInteger}
+	 *
+	 * @param number 数字
+	 * @return {@link BigInteger}
+	 * @since 5.4.5
+	 */
+	public static BigInteger toBigInteger(String number) {
+		return (null == number) ? BigInteger.ZERO : new BigInteger(number);
+	}
+
+	/**
 	 * 是否空白符<br>
 	 * 空白符包括空格、制表符、全角空格和不间断空格<br>
 	 *

+ 44 - 4
hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java

@@ -352,13 +352,39 @@ public class XmlUtil {
 	 *
 	 * @param doc XML文档
 	 * @return XML字符串
+	 * @since 5.4.5
 	 */
-	public static String toStr(Document doc) {
+	public static String toStr(Node doc) {
 		return toStr(doc, false);
 	}
 
 	/**
 	 * 将XML文档转换为String<br>
+	 * 字符编码使用XML文档中的编码,获取不到则使用UTF-8<br>
+	 * 默认非格式化输出,若想格式化请使用{@link #format(Document)}
+	 *
+	 * @param doc XML文档
+	 * @return XML字符串
+	 */
+	public static String toStr(Document doc) {
+		return toStr((Node)doc);
+	}
+
+	/**
+	 * 将XML文档转换为String<br>
+	 * 字符编码使用XML文档中的编码,获取不到则使用UTF-8
+	 *
+	 * @param doc      XML文档
+	 * @param isPretty 是否格式化输出
+	 * @return XML字符串
+	 * @since 5.4.5
+	 */
+	public static String toStr(Node doc, boolean isPretty) {
+		return toStr(doc, CharsetUtil.UTF_8, isPretty);
+	}
+
+	/**
+	 * 将XML文档转换为String<br>
 	 * 字符编码使用XML文档中的编码,获取不到则使用UTF-8
 	 *
 	 * @param doc      XML文档
@@ -367,7 +393,21 @@ public class XmlUtil {
 	 * @since 3.0.9
 	 */
 	public static String toStr(Document doc, boolean isPretty) {
-		return toStr(doc, CharsetUtil.UTF_8, isPretty);
+		return toStr((Node)doc, isPretty);
+	}
+
+	/**
+	 * 将XML文档转换为String<br>
+	 * 字符编码使用XML文档中的编码,获取不到则使用UTF-8
+	 *
+	 * @param doc      XML文档
+	 * @param charset  编码
+	 * @param isPretty 是否格式化输出
+	 * @return XML字符串
+	 * @since 5.4.5
+	 */
+	public static String toStr(Node doc, String charset, boolean isPretty) {
+		return toStr(doc, charset, isPretty, false);
 	}
 
 	/**
@@ -381,7 +421,7 @@ public class XmlUtil {
 	 * @since 3.0.9
 	 */
 	public static String toStr(Document doc, String charset, boolean isPretty) {
-		return toStr(doc, charset, isPretty, false);
+		return toStr((Node)doc, charset, isPretty);
 	}
 
 	/**
@@ -395,7 +435,7 @@ public class XmlUtil {
 	 * @return XML字符串
 	 * @since 5.1.2
 	 */
-	public static String toStr(Document doc, String charset, boolean isPretty, boolean omitXmlDeclaration) {
+	public static String toStr(Node doc, String charset, boolean isPretty, boolean omitXmlDeclaration) {
 		final StringWriter writer = StrUtil.getWriter();
 		try {
 			write(doc, writer, charset, isPretty ? INDENT_DEFAULT : 0, omitXmlDeclaration);

+ 16 - 0
hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java

@@ -9,6 +9,8 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicIntegerArray;
+import java.util.concurrent.atomic.AtomicLongArray;
 
 /**
  * 类型转换工具单元测试
@@ -222,6 +224,20 @@ public class ConvertTest {
 		Assert.assertEquals("5.1.1", product.getVersion());
 	}
 
+	@Test
+	public void toAtomicIntegerArrayTest(){
+		String str = "1,2";
+		final AtomicIntegerArray atomicIntegerArray = Convert.convert(AtomicIntegerArray.class, str);
+		Assert.assertEquals("[1, 2]", atomicIntegerArray.toString());
+	}
+
+	@Test
+	public void toAtomicLongArrayTest(){
+		String str = "1,2";
+		final AtomicLongArray atomicLongArray = Convert.convert(AtomicLongArray.class, str);
+		Assert.assertEquals("[1, 2]", atomicLongArray.toString());
+	}
+
 	@Data
 	@AllArgsConstructor
 	public static class Product implements Serializable {

+ 15 - 0
hutool-core/src/test/java/cn/hutool/core/convert/StringConvertTest.java

@@ -0,0 +1,15 @@
+package cn.hutool.core.convert;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.TimeZone;
+
+public class StringConvertTest {
+
+	@Test
+	public void timezoneToStrTest(){
+		final String s = Convert.toStr(TimeZone.getTimeZone("Asia/Shanghai"));
+		Assert.assertEquals("Asia/Shanghai", s);
+	}
+}

BIN
hutool-extra/bopomofo4j-temp/bopomofo4j-c6e41074-5302-42b6-9bdf-8742cb416a62.jar


+ 6 - 0
hutool-extra/pom.xml

@@ -234,6 +234,12 @@
 			<optional>true</optional>
 		</dependency>
 		<dependency>
+			<groupId>com.rnkrsoft.bopomofo4j</groupId>
+			<artifactId>bopomofo4j</artifactId>
+			<version>1.0.0</version>
+			<optional>true</optional>
+		</dependency>
+		<dependency>
 			<groupId>cglib</groupId>
 			<artifactId>cglib</artifactId>
 			<version>${cglib.version}</version>

+ 43 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/Bopomofo4jEngine.java

@@ -0,0 +1,43 @@
+package cn.hutool.extra.pinyin.engine.bopomofo4j;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.pinyin.PinyinEngine;
+import com.rnkrsoft.bopomofo4j.Bopomofo4j;
+import com.rnkrsoft.bopomofo4j.ToneType;
+
+/**
+ * 封装了Bopomofo4j的引擎。
+ *
+ * <p>
+ * Bopomofo4j封装,项目:https://gitee.com/rnkrsoft/Bopomofo4j。
+ * </p>
+ *
+ * <p>
+ * 引入:
+ * <pre>
+ * &lt;dependency&gt;
+ *     &lt;groupId&gt;com.rnkrsoft.bopomofo4j&lt;/groupId&gt;
+ *     &lt;artifactId&gt;bopomofo4j&lt;/artifactId&gt;
+ *     &lt;version&gt;1.0.0&lt;/version&gt;
+ * &lt;/dependency&gt;
+ * </pre>
+ *
+ * @author looly
+ * @since 5.4.5
+ */
+public class Bopomofo4jEngine implements PinyinEngine {
+
+	public Bopomofo4jEngine(){
+		Bopomofo4j.local();
+	}
+
+	@Override
+	public String getPinyin(char c) {
+		return Bopomofo4j.pinyin(String.valueOf(c), ToneType.WITHOUT_TONE, false, false, StrUtil.EMPTY);
+	}
+
+	@Override
+	public String getPinyin(String str, String separator) {
+		return Bopomofo4j.pinyin(str, ToneType.WITHOUT_TONE, false, false, separator);
+	}
+}

+ 20 - 0
hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/package-info.java

@@ -0,0 +1,20 @@
+/**
+ * 封装了Bopomofo4j的引擎。
+ *
+ * <p>
+ * Bopomofo4j封装,项目:https://gitee.com/rnkrsoft/Bopomofo4j。
+ * </p>
+ *
+ * <p>
+ * 引入:
+ * <pre>
+ * &lt;dependency&gt;
+ *     &lt;groupId&gt;com.rnkrsoft.bopomofo4j&lt;/groupId&gt;
+ *     &lt;artifactId&gt;bopomofo4j&lt;/artifactId&gt;
+ *     &lt;version&gt;1.0.0&lt;/version&gt;
+ * &lt;/dependency&gt;
+ * </pre>
+ *
+ * @author looly
+ */
+package cn.hutool.extra.pinyin.engine.bopomofo4j;

+ 2 - 1
hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.pinyin.PinyinEngine

@@ -1,3 +1,4 @@
 cn.hutool.extra.pinyin.engine.tinypinyin.TinyPinyinEngine
 cn.hutool.extra.pinyin.engine.jpinyin.JPinyinEngine
-cn.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine
+cn.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine
+cn.hutool.extra.pinyin.engine.bopomofo4j.Bopomofo4jEngine

+ 15 - 0
hutool-extra/src/test/java/cn/hutool/extra/pinyin/PinyinUtilTest.java

@@ -1,5 +1,6 @@
 package cn.hutool.extra.pinyin;
 
+import cn.hutool.extra.pinyin.engine.bopomofo4j.Bopomofo4jEngine;
 import cn.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine;
 import org.junit.Assert;
 import org.junit.Test;
@@ -20,6 +21,13 @@ public class PinyinUtilTest {
 	}
 
 	@Test
+	public void getPinyinByBopomofo4jTest() {
+		final Bopomofo4jEngine engine = new Bopomofo4jEngine();
+		final String pinyin = engine.getPinyin("你好h", " ");
+		Assert.assertEquals("ni haoh", pinyin);
+	}
+
+	@Test
 	public void getPinyinUpperCaseTest(){
 		final String pinyin = PinyinUtil.getPinyin("你好怡", " ");
 		Assert.assertEquals("ni hao yi", pinyin);
@@ -37,4 +45,11 @@ public class PinyinUtilTest {
 		final String result = engine.getFirstLetter("林海", "");
 		Assert.assertEquals("lh", result);
 	}
+
+	@Test
+	public void getFirstLetterByBopomofo4jTest(){
+		final Bopomofo4jEngine engine = new Bopomofo4jEngine();
+		final String result = engine.getFirstLetter("林海", "");
+		Assert.assertEquals("lh", result);
+	}
 }

+ 4 - 0
hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java

@@ -2,6 +2,7 @@ package cn.hutool.json;
 
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.TemporalAccessorUtil;
 import cn.hutool.core.util.CharUtil;
 import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.ObjectUtil;
@@ -239,6 +240,9 @@ final class InternalJSONUtil {
 	 */
 	private static String formatDate(Object dateObj, String format) {
 		if (StrUtil.isNotBlank(format)) {
+			if(dateObj instanceof TemporalAccessor){
+				return TemporalAccessorUtil.format((TemporalAccessor) dateObj, format);
+			}
 			//用户定义了日期格式
 			return JSONUtil.quote(DateUtil.format(Convert.toDate(dateObj), format));
 		}

+ 27 - 25
hutool-json/src/main/java/cn/hutool/json/JSONObject.java

@@ -351,6 +351,18 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
 	@Override
 	@Deprecated
 	public JSONObject put(String key, Object value) throws JSONException {
+		return set(key, value);
+	}
+
+	/**
+	 * 设置键值对到JSONObject中,在忽略null模式下,如果值为<code>null</code>,将此键移除
+	 *
+	 * @param key   键
+	 * @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
+	 * @return this.
+	 * @throws JSONException 值是无穷数字抛出此异常
+	 */
+	public JSONObject set(String key, Object value) throws JSONException {
 		if (null == key) {
 			return this;
 		}
@@ -367,19 +379,6 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
 	}
 
 	/**
-	 * 设置键值对到JSONObject中,在忽略null模式下,如果值为<code>null</code>,将此键移除
-	 *
-	 * @param key   键
-	 * @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL.
-	 * @return this.
-	 * @throws JSONException 值是无穷数字抛出此异常
-	 */
-	public JSONObject set(String key, Object value) throws JSONException {
-		put(key, value);
-		return this;
-	}
-
-	/**
 	 * 一次性Put 键值对,如果key已经存在抛出异常,如果键值中有null值,忽略
 	 *
 	 * @param key   键
@@ -392,7 +391,7 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
 			if (rawHashMap.containsKey(key)) {
 				throw new JSONException("Duplicate key \"{}\"", key);
 			}
-			this.put(key, value);
+			this.set(key, value);
 		}
 		return this;
 	}
@@ -407,7 +406,7 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
 	 */
 	public JSONObject putOpt(String key, Object value) throws JSONException {
 		if (key != null && value != null) {
-			this.put(key, value);
+			this.set(key, value);
 		}
 		return this;
 	}
@@ -415,7 +414,7 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
 	@Override
 	public void putAll(Map<? extends String, ?> m) {
 		for (Entry<? extends String, ?> entry : m.entrySet()) {
-			this.put(entry.getKey(), entry.getValue());
+			this.set(entry.getKey(), entry.getValue());
 		}
 	}
 
@@ -432,7 +431,7 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
 		InternalJSONUtil.testValidity(value);
 		Object object = this.getObj(key);
 		if (object == null) {
-			this.put(key, value instanceof JSONArray ? new JSONArray(this.config).set(value) : value);
+			this.set(key, value instanceof JSONArray ? new JSONArray(this.config).set(value) : value);
 		} else if (object instanceof JSONArray) {
 			((JSONArray) object).set(value);
 		} else {
@@ -472,19 +471,19 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
 	public JSONObject increment(String key) throws JSONException {
 		Object value = this.getObj(key);
 		if (value == null) {
-			this.put(key, 1);
+			this.set(key, 1);
 		} else if (value instanceof BigInteger) {
-			this.put(key, ((BigInteger) value).add(BigInteger.ONE));
+			this.set(key, ((BigInteger) value).add(BigInteger.ONE));
 		} else if (value instanceof BigDecimal) {
-			this.put(key, ((BigDecimal) value).add(BigDecimal.ONE));
+			this.set(key, ((BigDecimal) value).add(BigDecimal.ONE));
 		} else if (value instanceof Integer) {
-			this.put(key, (Integer) value + 1);
+			this.set(key, (Integer) value + 1);
 		} else if (value instanceof Long) {
-			this.put(key, (Long) value + 1);
+			this.set(key, (Long) value + 1);
 		} else if (value instanceof Double) {
-			this.put(key, (Double) value + 1);
+			this.set(key, (Double) value + 1);
 		} else if (value instanceof Float) {
-			this.put(key, (Float) value + 1);
+			this.set(key, (Float) value + 1);
 		} else {
 			throw new JSONException("Unable to increment [" + JSONUtil.quote(key) + "].");
 		}
@@ -652,8 +651,11 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
 		} else if (source instanceof Map) {
 			// Map
 			for (final Entry<?, ?> e : ((Map<?, ?>) source).entrySet()) {
-				this.put(Convert.toStr(e.getKey()), e.getValue());
+				this.set(Convert.toStr(e.getKey()), e.getValue());
 			}
+		}else if (source instanceof Map.Entry) {
+			final Map.Entry entry = (Map.Entry) source;
+			this.set(Convert.toStr(entry.getKey()), entry.getValue());
 		} else if (source instanceof CharSequence) {
 			// 可能为JSON字符串
 			init((CharSequence) source);

+ 23 - 0
hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java

@@ -9,6 +9,7 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.io.resource.ResourceUtil;
 import cn.hutool.core.lang.Console;
+import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.test.bean.JSONBean;
 import cn.hutool.json.test.bean.ResultDto;
@@ -27,9 +28,13 @@ import org.junit.Ignore;
 import org.junit.Test;
 
 import java.math.BigDecimal;
+import java.sql.Timestamp;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * JSONObject单元测试
@@ -425,6 +430,14 @@ public class JSONObjectTest {
 		Assert.assertEquals("{\"date\":[\"2020-06-05 11:16:11\"],\"bbb\":[\"222\"],\"aaa\":[\"123\"]}", json.toString());
 	}
 
+	@Test
+	public void getTimestampTest(){
+		String timeStr = "1970-01-01 00:00:00";
+		final JSONObject jsonObject = JSONUtil.createObj().set("time", timeStr);
+		final Timestamp time = jsonObject.get("time", Timestamp.class);
+		Assert.assertEquals("1970-01-01 00:00:00.0", time.toString());
+	}
+
 	public enum TestEnum {
 		TYPE_A, TYPE_B
 	}
@@ -497,4 +510,14 @@ public class JSONObjectTest {
 			return this.fieldToIgnore;
 		}
 	}
+
+	@Test
+	public void setEntryTest(){
+		final HashMap<String, String> of = MapUtil.of("test", "testValue");
+		final Set<Map.Entry<String, String>> entries = of.entrySet();
+		final Map.Entry<String, String> next = entries.iterator().next();
+
+		final JSONObject jsonObject = JSONUtil.parseObj(next);
+		Console.log(jsonObject);
+	}
 }