浏览代码

fix json double

Looly 5 年之前
父节点
当前提交
c4fdf545e7

+ 2 - 1
CHANGELOG.md

@@ -3,7 +3,7 @@
 
 -------------------------------------------------------------------------------------------------------------
 
-# 5.4.5 (2020-10-09)
+# 5.4.5 (2020-10-11)
 
 ### 新特性
 * 【core   】     ConsoleTable代码优化(pr#190@Gitee)
@@ -18,6 +18,7 @@
 ### Bug修复
 * 【core   】     解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee)
 * 【core   】     解决ListUtil计算总量可能的int溢出问题(pr#1150@Github)
+* 【json   】     解决JSON中转换为double小数精度丢失问题(pr#192@Gitee)
 
 -------------------------------------------------------------------------------------------------------------
 

+ 17 - 8
hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java

@@ -140,12 +140,14 @@ final class InternalJSONUtil {
 	 * @return A simple JSON value.
 	 */
 	protected static Object stringToValue(String string) {
+		// null处理
 		if (null == string || "null".equalsIgnoreCase(string)) {
 			return JSONNull.NULL;
 		}
 
-		if (StrUtil.EMPTY.equals(string)) {
-			return string;
+		// boolean处理
+		if (0 == string.length()) {
+			return StrUtil.EMPTY;
 		}
 		if ("true".equalsIgnoreCase(string)) {
 			return Boolean.TRUE;
@@ -154,17 +156,22 @@ final class InternalJSONUtil {
 			return Boolean.FALSE;
 		}
 
-		/* If it might be a number, try converting it. If a number cannot be produced, then the value will just be a string. */
+		// Number处理
 		char b = string.charAt(0);
 		if ((b >= '0' && b <= '9') || b == '-') {
 			try {
-				if (string.indexOf('.') > -1 || string.indexOf('e') > -1 || string.indexOf('E') > -1) {
+				if (StrUtil.containsAnyIgnoreCase(string, ".", "e")) {
+					// pr#192@Gitee,Double会出现小数精度丢失问题,此处使用BigDecimal
+					//double d = Double.parseDouble(string);
+					//if (false == Double.isInfinite(d) && false == Double.isNaN(d)) {
+					//	return d;
+					//}
 					return new BigDecimal(string);
 				} else {
-					Long myLong = new Long(string);
-					if (string.equals(myLong.toString())) {
-						if (myLong == myLong.intValue()) {
-							return myLong.intValue();
+					final long myLong = Long.parseLong(string);
+					if (string.equals(Long.toString(myLong))) {
+						if (myLong == (int) myLong) {
+							return (int) myLong;
 						} else {
 							return myLong;
 						}
@@ -173,6 +180,8 @@ final class InternalJSONUtil {
 			} catch (Exception ignore) {
 			}
 		}
+
+		// 其它情况返回原String值下
 		return string;
 	}
 

+ 1 - 1
hutool-json/src/main/java/cn/hutool/json/JSONTokener.java

@@ -349,7 +349,7 @@ public class JSONTokener {
 		this.back();
 
 		string = sb.toString().trim();
-		if ("".equals(string)) {
+		if (0 == string.length()) {
 			throw this.syntaxError("Missing value");
 		}
 		return InternalJSONUtil.stringToValue(string);

+ 0 - 68
hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java

@@ -10,10 +10,8 @@ import cn.hutool.json.test.bean.UserC;
 import org.junit.Assert;
 import org.junit.Test;
 
-import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 public class JSONUtilTest {
@@ -127,15 +125,6 @@ public class JSONUtilTest {
 	}
 
 	@Test
-	public void toBeanTest3() {
-		//		测试数字类型精度丢失的情况
-		String number = "1234.123456789123456";
-		String jsonString = "{\"create\":{\"details\":[{\"price\":" + number + "}]}}";
-		WebCreate create = JSONUtil.toBean(jsonString, WebCreate.class);
-		Assert.assertEquals(number,create.getCreate().getDetails().get(0).getPrice().toString());
-	}
-
-	@Test
 	public void putByPathTest() {
 		JSONObject json = new JSONObject();
 		json.putByPath("aa.bb", "BB");
@@ -172,62 +161,5 @@ public class JSONUtilTest {
 		final JSONObject jsonObject = JSONUtil.parseObj(json);
 		Assert.assertEquals("12.00", jsonObject.getBigDecimal("test").setScale(2).toString());
 	}
-
-
-	class WebCreate {
-		private Create create;
-		@Override
-		public String toString() {
-			return "WebCreate{" +
-					"create=" + create +
-					'}';
-		}
-
-		public void setCreate(Create create) {
-			this.create = create;
-		}
-
-		public Create getCreate() {
-			return create;
-		}
-	}
-
-	class Create {
-		@Override
-		public String toString() {
-			return "Create{" +
-					"details=" + details +
-					'}';
-		}
-
-		private List<Detail> details;
-
-		public void setDetails(List<Detail> details) {
-			this.details = details;
-		}
-
-		public List<Detail> getDetails() {
-			return details;
-		}
-	}
-
-	class Detail {
-		private BigDecimal price;
-
-		public void setPrice(BigDecimal price) {
-			this.price = price;
-		}
-
-		@Override
-		public String toString() {
-			return "Detail{" +
-					"price=" + price +
-					'}';
-		}
-
-		public BigDecimal getPrice() {
-			return price;
-		}
-	}
 }
 

+ 75 - 0
hutool-json/src/test/java/cn/hutool/json/Pr192Test.java

@@ -0,0 +1,75 @@
+package cn.hutool.json;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+public class Pr192Test {
+
+	@Test
+	public void toBeanTest3() {
+		//		测试数字类型精度丢失的情况
+		String number = "1234.123456789123456";
+		String jsonString = "{\"create\":{\"details\":[{\"price\":" + number + "}]}}";
+		WebCreate create = JSONUtil.toBean(jsonString, WebCreate.class);
+		Assert.assertEquals(number,create.getCreate().getDetails().get(0).getPrice().toString());
+	}
+
+	static class WebCreate {
+		private Create create;
+		@Override
+		public String toString() {
+			return "WebCreate{" +
+					"create=" + create +
+					'}';
+		}
+
+		public void setCreate(Create create) {
+			this.create = create;
+		}
+
+		public Create getCreate() {
+			return create;
+		}
+	}
+
+	static class Create {
+		@Override
+		public String toString() {
+			return "Create{" +
+					"details=" + details +
+					'}';
+		}
+
+		private List<Detail> details;
+
+		public void setDetails(List<Detail> details) {
+			this.details = details;
+		}
+
+		public List<Detail> getDetails() {
+			return details;
+		}
+	}
+
+	static class Detail {
+		private BigDecimal price;
+
+		public void setPrice(BigDecimal price) {
+			this.price = price;
+		}
+
+		@Override
+		public String toString() {
+			return "Detail{" +
+					"price=" + price +
+					'}';
+		}
+
+		public BigDecimal getPrice() {
+			return price;
+		}
+	}
+}