mirror of https://github.com/alibaba/fastjson2.git
				
				
				
			* fix: issue #3293 and issue #3328 * refactor: simply some redundant code
This commit is contained in:
		
							parent
							
								
									62e344f5d9
								
							
						
					
					
						commit
						ca10dea7ec
					
				|  | @ -392,6 +392,60 @@ public final class ObjectWriterImplMap | ||||||
|         jsonWriter.endObject(); |         jsonWriter.endObject(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     static boolean isWriteAsString(Object val, long features) { | ||||||
|  |         return (features & (WriteNonStringKeyAsString.mask | BrowserCompatible.mask)) != 0 | ||||||
|  |                 && ObjectWriterProvider.isPrimitiveOrEnum(val.getClass()) | ||||||
|  |                 && !(val instanceof Temporal || val instanceof Date); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     String mapKeyToString(Object key, JSONWriter jsonWriter, long features) { | ||||||
|  |         if (key == null) { | ||||||
|  |             return null; | ||||||
|  |         } else if (key instanceof String) { | ||||||
|  |             return (String) key; | ||||||
|  |         } else if (key instanceof Integer || key instanceof Long) { | ||||||
|  |             return key.toString(); | ||||||
|  |         } | ||||||
|  |         if (isWriteAsString(key, features)) { | ||||||
|  |             return key.toString(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         final JSONWriter.Context context = jsonWriter.getContext(); | ||||||
|  |         String str = JSON.toJSONString(key, context); | ||||||
|  |         if (str != null) { | ||||||
|  |             final int length = str.length(); | ||||||
|  |             if (length > 1) { | ||||||
|  |                 final char quote = jsonWriter.useSingleQuote ? '\'' : '"'; | ||||||
|  |                 if (str.charAt(0) == quote && str.charAt(length - 1) == quote) { | ||||||
|  |                     return str.substring(1, length - 1); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return str; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     String writeMapKey(Object key, JSONWriter jsonWriter, long features) { | ||||||
|  |         String strKey = null; | ||||||
|  |         if (key == null) { | ||||||
|  |             jsonWriter.writeName("null"); | ||||||
|  |         } else if (key instanceof String) { | ||||||
|  |             jsonWriter.writeName(strKey = (String) key); | ||||||
|  |         } else { | ||||||
|  |             if (isWriteAsString(key, features)) { | ||||||
|  |                 jsonWriter.writeName(strKey = key.toString()); | ||||||
|  |             } else { | ||||||
|  |                 if (key instanceof Integer) { | ||||||
|  |                     jsonWriter.writeName((Integer) key); | ||||||
|  |                 } else if (key instanceof Long) { | ||||||
|  |                     jsonWriter.writeName((Long) key); | ||||||
|  |                 } else { | ||||||
|  |                     jsonWriter.writeNameAny(key); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return strKey; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public boolean writeTypeInfo(JSONWriter jsonWriter) { |     public boolean writeTypeInfo(JSONWriter jsonWriter) { | ||||||
|         if (jsonWriter.utf8) { |         if (jsonWriter.utf8) { | ||||||
|  | @ -438,28 +492,12 @@ public final class ObjectWriterImplMap | ||||||
| 
 | 
 | ||||||
|         ObjectWriterProvider provider = jsonWriter.context.provider; |         ObjectWriterProvider provider = jsonWriter.context.provider; | ||||||
|         for (Map.Entry entry : (Iterable<Map.Entry>) map.entrySet()) { |         for (Map.Entry entry : (Iterable<Map.Entry>) map.entrySet()) { | ||||||
|             Object value = entry.getValue(); |             final Object value = entry.getValue(); | ||||||
|             Object key = entry.getKey(); |             Object key = entry.getKey(); | ||||||
| 
 | 
 | ||||||
|             if (value == null) { |             if (value == null) { | ||||||
|                 if ((features & JSONWriter.Feature.WriteNulls.mask) != 0) { |                 if ((features & JSONWriter.Feature.WriteNulls.mask) != 0) { | ||||||
|                     if (key == null) { |                     writeMapKey(key, jsonWriter, features); | ||||||
|                         jsonWriter.writeName("null"); |  | ||||||
|                     } else if (key instanceof String) { |  | ||||||
|                         jsonWriter.writeName((String) key); |  | ||||||
|                     } else { |  | ||||||
|                         if ((features & (WriteNonStringKeyAsString.mask | BrowserCompatible.mask)) != 0) { |  | ||||||
|                             jsonWriter.writeName(key.toString()); |  | ||||||
|                         } else { |  | ||||||
|                             if (key instanceof Integer) { |  | ||||||
|                                 jsonWriter.writeName((Integer) key); |  | ||||||
|                             } else if (key instanceof Long) { |  | ||||||
|                                 jsonWriter.writeName((Long) key); |  | ||||||
|                             } else { |  | ||||||
|                                 jsonWriter.writeNameAny(key); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     jsonWriter.writeColon(); |                     jsonWriter.writeColon(); | ||||||
|                     jsonWriter.writeNull(); |                     jsonWriter.writeNull(); | ||||||
|                 } |                 } | ||||||
|  | @ -476,33 +514,14 @@ public final class ObjectWriterImplMap | ||||||
|             String strKey = null; |             String strKey = null; | ||||||
|             if (keyWriter != null) { |             if (keyWriter != null) { | ||||||
|                 keyWriter.write(jsonWriter, key, null, null, 0); |                 keyWriter.write(jsonWriter, key, null, null, 0); | ||||||
|             } else if (key == null) { |  | ||||||
|                 jsonWriter.writeName("null"); |  | ||||||
|             } else if (key instanceof String) { |  | ||||||
|                 jsonWriter.writeName(strKey = (String) key); |  | ||||||
|             } else { |             } else { | ||||||
|                 boolean writeAsString = (features & (WriteNonStringKeyAsString.mask | BrowserCompatible.mask)) != 0 && ObjectWriterProvider.isPrimitiveOrEnum(key.getClass()); |                 strKey = writeMapKey(key, jsonWriter, features); | ||||||
|                 if (writeAsString && (key instanceof Temporal || key instanceof Date)) { |  | ||||||
|                     writeAsString = false; |  | ||||||
|                 } |  | ||||||
|                 if (writeAsString) { |  | ||||||
|                     jsonWriter.writeName(strKey = key.toString()); |  | ||||||
|                 } else { |  | ||||||
|                     if (key instanceof Integer) { |  | ||||||
|                         jsonWriter.writeName((Integer) key); |  | ||||||
|                     } else if (key instanceof Long) { |  | ||||||
|                         long longKey = (Long) key; |  | ||||||
|                         jsonWriter.writeName(longKey); |  | ||||||
|                     } else { |  | ||||||
|                         jsonWriter.writeNameAny(key); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             jsonWriter.writeColon(); |             jsonWriter.writeColon(); | ||||||
| 
 | 
 | ||||||
|             Class valueClass; |             Class<?> valueClass; | ||||||
|             if (contentAs) { |             if (contentAs) { | ||||||
|                 valueClass = (Class) this.valueType; |                 valueClass = (Class<?>) this.valueType; | ||||||
|             } else { |             } else { | ||||||
|                 valueClass = value.getClass(); |                 valueClass = value.getClass(); | ||||||
|             } |             } | ||||||
|  | @ -516,7 +535,7 @@ public final class ObjectWriterImplMap | ||||||
|                 if ((provider.userDefineMask & ObjectWriterProvider.TYPE_INT64_MASK) == 0) { |                 if ((provider.userDefineMask & ObjectWriterProvider.TYPE_INT64_MASK) == 0) { | ||||||
|                     jsonWriter.writeInt64((Long) value); |                     jsonWriter.writeInt64((Long) value); | ||||||
|                 } else { |                 } else { | ||||||
|                     ObjectWriter valueWriter = jsonWriter.getObjectWriter(valueClass); |                     ObjectWriter<?> valueWriter = jsonWriter.getObjectWriter(valueClass); | ||||||
|                     valueWriter.write(jsonWriter, value, strKey, Long.class, features); |                     valueWriter.write(jsonWriter, value, strKey, Long.class, features); | ||||||
|                 } |                 } | ||||||
|                 continue; |                 continue; | ||||||
|  | @ -527,14 +546,14 @@ public final class ObjectWriterImplMap | ||||||
|                 if ((provider.userDefineMask & ObjectWriterProvider.TYPE_DECIMAL_MASK) == 0) { |                 if ((provider.userDefineMask & ObjectWriterProvider.TYPE_DECIMAL_MASK) == 0) { | ||||||
|                     jsonWriter.writeDecimal((BigDecimal) value, features, null); |                     jsonWriter.writeDecimal((BigDecimal) value, features, null); | ||||||
|                 } else { |                 } else { | ||||||
|                     ObjectWriter valueWriter = jsonWriter.getObjectWriter(valueClass); |                     ObjectWriter<?> valueWriter = jsonWriter.getObjectWriter(valueClass); | ||||||
|                     valueWriter.write(jsonWriter, value, key, this.valueType, this.features); |                     valueWriter.write(jsonWriter, value, key, this.valueType, this.features); | ||||||
|                 } |                 } | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             boolean isPrimitiveOrEnum; |             boolean isPrimitiveOrEnum; | ||||||
|             ObjectWriter valueWriter; |             ObjectWriter<?> valueWriter; | ||||||
|             if (valueClass == this.valueType) { |             if (valueClass == this.valueType) { | ||||||
|                 if (this.valueWriter != null) { |                 if (this.valueWriter != null) { | ||||||
|                     valueWriter = this.valueWriter; |                     valueWriter = this.valueWriter; | ||||||
|  | @ -559,7 +578,7 @@ public final class ObjectWriterImplMap | ||||||
|                     isPrimitiveOrEnum = false; |                     isPrimitiveOrEnum = false; | ||||||
|                 } else { |                 } else { | ||||||
|                     valueWriter = jsonWriter.getObjectWriter(valueClass); |                     valueWriter = jsonWriter.getObjectWriter(valueClass); | ||||||
|                     isPrimitiveOrEnum = ObjectWriterProvider.isPrimitiveOrEnum(value.getClass()); |                     isPrimitiveOrEnum = ObjectWriterProvider.isPrimitiveOrEnum(valueClass); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -628,14 +647,7 @@ public final class ObjectWriterImplMap | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             Object entryKey = entry.getKey(); |             Object entryKey = entry.getKey(); | ||||||
|             String key; |             String key = mapKeyToString(entryKey, jsonWriter, features); | ||||||
|             if (entryKey == null) { |  | ||||||
|                 key = null; |  | ||||||
|             } else if (entryKey instanceof String) { |  | ||||||
|                 key = (String) entryKey; |  | ||||||
|             } else { |  | ||||||
|                 key = JSON.toJSONString(entryKey, jsonWriter.getContext()); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             if (refDetect) { |             if (refDetect) { | ||||||
|                 String refPath = jsonWriter.setPath(key, value); |                 String refPath = jsonWriter.setPath(key, value); | ||||||
|  | @ -681,13 +693,13 @@ public final class ObjectWriterImplMap | ||||||
|                 if (value == null) { |                 if (value == null) { | ||||||
|                     jsonWriter.writeNull(); |                     jsonWriter.writeNull(); | ||||||
|                 } else { |                 } else { | ||||||
|                     Class valueClass; |                     Class<?> valueClass; | ||||||
|                     if (contentAs) { |                     if (contentAs) { | ||||||
|                         valueClass = (Class) this.valueType; |                         valueClass = (Class<?>) this.valueType; | ||||||
|                     } else { |                     } else { | ||||||
|                         valueClass = value.getClass(); |                         valueClass = value.getClass(); | ||||||
|                     } |                     } | ||||||
|                     ObjectWriter valueWriter = jsonWriter.getObjectWriter(valueClass); |                     ObjectWriter<?> valueWriter = jsonWriter.getObjectWriter(valueClass); | ||||||
|                     valueWriter.write(jsonWriter, value, fieldName, fieldType, this.features); |                     valueWriter.write(jsonWriter, value, fieldName, fieldType, this.features); | ||||||
|                 } |                 } | ||||||
|             } finally { |             } finally { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,86 @@ | ||||||
|  | package com.alibaba.fastjson2.issues_3200; | ||||||
|  | 
 | ||||||
|  | import com.alibaba.fastjson2.JSON; | ||||||
|  | import com.alibaba.fastjson2.JSONWriter; | ||||||
|  | import com.alibaba.fastjson2.filter.ValueFilter; | ||||||
|  | import org.junit.Test; | ||||||
|  | 
 | ||||||
|  | import java.math.BigDecimal; | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | import java.time.ZoneId; | ||||||
|  | import java.util.*; | ||||||
|  | 
 | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertEquals; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertTrue; | ||||||
|  | 
 | ||||||
|  | public class Issue3293 { | ||||||
|  |     public interface ValueEnum<V> { | ||||||
|  |         /** | ||||||
|  |          * 获取枚举的 value 值 | ||||||
|  |          */ | ||||||
|  |         V getValue(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public enum MemberType implements ValueEnum<Integer> { | ||||||
|  |         USER(1), | ||||||
|  |         ADMIN(2), | ||||||
|  |         AGENT(3); | ||||||
|  | 
 | ||||||
|  |         final Integer value; | ||||||
|  | 
 | ||||||
|  |         MemberType(Integer value) { | ||||||
|  |             this.value = value; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         @Override | ||||||
|  |         public Integer getValue() { | ||||||
|  |             return value; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void test() { | ||||||
|  |         final ValueFilter valueFilter = (object, name, value) -> { | ||||||
|  |             if (value instanceof Enum<?>) { | ||||||
|  |                 if (value instanceof ValueEnum<?>) { | ||||||
|  |                     return ((ValueEnum<?>) value).getValue(); | ||||||
|  |                 } | ||||||
|  |                 return ((Enum<?>) value).ordinal(); | ||||||
|  |             } | ||||||
|  |             return value; | ||||||
|  |         }; | ||||||
|  |         LocalDateTime localDateTime = LocalDateTime.of(2006, 1, 2, 15, 4, 5); | ||||||
|  |         Map<Object, Object> map = new HashMap<>(4); | ||||||
|  |         map.put(MemberType.USER, 1); | ||||||
|  |         map.put(MemberType.ADMIN, 2); | ||||||
|  |         map.put(123, "a"); | ||||||
|  |         map.put("key", "value"); | ||||||
|  |         map.put(localDateTime, false); | ||||||
|  |         Date date = Date.from(localDateTime.plusDays(1).atZone(ZoneId.systemDefault()).toInstant()); | ||||||
|  |         map.put(date, true); | ||||||
|  |         map.put(BigDecimal.TEN, 10); | ||||||
|  |         map.put(Collections.emptyList(), 3L); | ||||||
|  |         map.put(Collections.emptyMap(), "null"); | ||||||
|  | 
 | ||||||
|  |         // {"USER":1,{}:"null",[]:3,"ADMIN":2,"2006-01-03 15:04:05":true,10:10,123:"a","2006-01-02 15:04:05":false,"key":"value"} | ||||||
|  |         String rawJsonStr = JSON.toJSONString(map); | ||||||
|  |         // System.out.println(rawJsonStr); | ||||||
|  |         assertTrue(rawJsonStr.contains("\"USER\"")); | ||||||
|  |         assertTrue(rawJsonStr.contains("{}:")); | ||||||
|  |         assertTrue(rawJsonStr.contains("[]:")); | ||||||
|  |         assertTrue(rawJsonStr.contains("10:")); | ||||||
|  |         assertTrue(rawJsonStr.contains("\"2006-01-02 15:04:05\":")); | ||||||
|  | 
 | ||||||
|  |         // {"USER":1,"{}":"null","[]":3,"ADMIN":2,"2006-01-03 15:04:05":true,"10":10,"123":"a","2006-01-02 15:04:05":false,"key":"value"} | ||||||
|  |         String jsonStr1 = JSON.toJSONString(map, JSONWriter.Feature.WriteNonStringKeyAsString); | ||||||
|  |         String jsonStr2 = JSON.toJSONString(map, valueFilter, JSONWriter.Feature.BrowserCompatible); | ||||||
|  |         // System.out.println(jsonStr1); | ||||||
|  |         assertEquals(jsonStr1, jsonStr2); | ||||||
|  | 
 | ||||||
|  |         assertTrue(jsonStr1.contains("\"USER\"")); | ||||||
|  |         assertTrue(jsonStr1.contains("\"[]\":")); | ||||||
|  |         assertTrue(jsonStr1.contains("\"{}\":")); | ||||||
|  |         assertTrue(jsonStr1.contains("\"10\":")); | ||||||
|  |         assertTrue(jsonStr1.contains("\"2006-01-02 15:04:05\":")); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -15,16 +15,16 @@ public class BigDecimalUtil { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         int scale = value.scale(); |         int scale = value.scale(); | ||||||
|         DecimalFormat decimalFormat = null; |         DecimalFormat decimalFormat; | ||||||
|         if (scale <= 2) { |         if (scale <= 2) { | ||||||
|             decimalFormat = DF_TWO; |             decimalFormat = DF_TWO; | ||||||
|         } else if (scale > 2 && scale <= 4) { |         } else if (scale <= 4) { | ||||||
|             // 保留四位小数 |             // 保留四位小数 | ||||||
|             decimalFormat = DF_FOUR; |             decimalFormat = DF_FOUR; | ||||||
|         } else if (scale > 4 && scale <= 6) { |         } else if (scale <= 6) { | ||||||
|             // 保留六位小数 |             // 保留六位小数 | ||||||
|             decimalFormat = DF_SIX; |             decimalFormat = DF_SIX; | ||||||
|         } else if (scale > 6 && scale <= 8) { |         } else if (scale <= 8) { | ||||||
|             decimalFormat = EIGHT_SIX; |             decimalFormat = EIGHT_SIX; | ||||||
|         } else { |         } else { | ||||||
|             decimalFormat = null; |             decimalFormat = null; | ||||||
|  | @ -32,37 +32,32 @@ public class BigDecimalUtil { | ||||||
| 
 | 
 | ||||||
|         if (null == decimalFormat) { |         if (null == decimalFormat) { | ||||||
|             return value.toString(); |             return value.toString(); | ||||||
|         } else { |  | ||||||
|             return decimalFormat.format(value); |  | ||||||
|         } |         } | ||||||
|  |         // FIXME: decimalFormat is NOT thread safe | ||||||
|  |         return decimalFormat.format(value); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static BigDecimal castToBigDecimal(String value) { |     public static BigDecimal castToBigDecimal(String value) { | ||||||
|         if (null == value || value.length() < 1) { |         final int len; | ||||||
|  |         if (value == null || (len = value.length()) == 0) { | ||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // 只保留数字和小数点 |         // 只保留数字和小数点 | ||||||
|         StringBuilder sb = new StringBuilder(); |         final char[] validChars = new char[len]; | ||||||
|         char[] charArr = value.toCharArray(); |         int i = 0; | ||||||
|         for (char c : charArr) { |         for (int j = 0; j < len; j++) { | ||||||
|             // 0-9 |             final char c = value.charAt(j); | ||||||
|             if (c >= 48 && c <= 57) { |             if (c >= '0' && c <= '9' || c == '.') { | ||||||
|                 sb.append((char) c); |                 validChars[i++] = c; | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             // . |  | ||||||
|             if (c == 46) { |  | ||||||
|                 sb.append((char) c); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (sb.length() < 1) { |         if (i == 0) { | ||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         String decimal = sb.toString(); |         // new BigDecimal( stringBuilder.toString() ) will call new BigDecimal( str.toCharArray() ) internally | ||||||
|         BigDecimal result = new BigDecimal(decimal); |         return new BigDecimal(validChars, 0, i); | ||||||
|         return result; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue