解决fastjson无序的问题--从源码的角度来看

以前的fastjson我不清楚..

而且这个问题网上好像没什么答案...

so...

看了下源码,不得不说阿里大佬写的代码是真的给力啊...

解决方案主要有两种...

 

方案1:定义一个类继承TypeReference<T>

T为LinkedHashMap<String,Object>

例如:

import java.util.LinkedHashMap;

import com.alibaba.fastjson.TypeReference;

public class LinkedTypeReference extends TypeReference<LinkedHashMap<String,Object>> {

}

调用时使用:

 

 

JSONObject.parseObject(jsonString,new LinkedTypeReference());


方案2:两种方式均可

 

 

			columnJson = JSONObject.parseObject(jsonString,new LinkedHashMap<String,Object>().getClass());
			columnJson = JSONObject.parseObject(jsonString,LinkedHashMap.class);


接下来有兴趣的小伙伴可以来瞄一眼源码,看看这两种方式是否真的能见效呢...

直接以方案2为例,其实都是走的一样的接口..

核心类JSON.java

 

 @SuppressWarnings("unchecked")
    public static final <T> T parseObject(String text, Class<T> clazz, Feature... features) {
        return (T) parseObject(text, (Type) clazz, ParserConfig.getGlobalInstance(), DEFAULT_PARSER_FEATURE, features);
    }

这里可以看出,把class转成type了,构造函数就不进一步跟踪了,都是一个妈出来的,继续往里面看

 

    @SuppressWarnings("unchecked")
    public static final <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor,
                                          int featureValues, Feature... features) {
        if (input == null) {
            return null;
        }

        for (Feature featrue : features) {
            featureValues = Feature.config(featureValues, featrue, true);
        }

        DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);

        if (processor instanceof ExtraTypeProvider) {
            parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);
        }

        if (processor instanceof ExtraProcessor) {
            parser.getExtraProcessors().add((ExtraProcessor) processor);
        }

        T value = (T) parser.parseObject(clazz);//执行解析对象,以及解析什么对象,就是刚刚传过来的那个class了..

        parser.handleResovleTask(value);

        parser.close();

        return (T) value;
    }

我们看到T value = (T) parser.parseObject(clazz);了,现在是不是得要再深入一点...不然不满足啊...

 

    @SuppressWarnings("unchecked")
    public <T> T parseObject(Type type) {
        if (lexer.token() == JSONToken.NULL) {
            lexer.nextToken();
            return null;
        }

        if (lexer.token() == JSONToken.LITERAL_STRING) {
            type = TypeUtils.unwrap(type);
            if (type == byte[].class) {
                byte[] bytes = lexer.bytesValue();
                lexer.nextToken();
                return (T) bytes;
            }

            if (type == char[].class) {
                String strVal = lexer.stringVal();
                lexer.nextToken();
                return (T) strVal.toCharArray();
            }
        }

        ObjectDeserializer derializer = config.getDeserializer(type);//获取序列化方式

        try {
            return (T) derializer.deserialze(this, type, null);
        } catch (JSONException e) {
            throw e;
        } catch (Throwable e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

ObjectDeserializer derializer = config.getDeserializer(type);通过对应的type获取对应的序列化方式

 

    public ObjectDeserializer getDeserializer(Type type) {
        ObjectDeserializer derializer = this.derializers.get(type);
        if (derializer != null) {
            return derializer;
        }

        if (type instanceof Class<?>) {
            return getDeserializer((Class<?>) type, type);
        }

        if (type instanceof ParameterizedType) {
            Type rawType = ((ParameterizedType) type).getRawType();
            if (rawType instanceof Class<?>) {
                return getDeserializer((Class<?>) rawType, type);
            } else {
                return getDeserializer(rawType);
            }
        }

        return JavaObjectDeserializer.instance;
    }

此处ObjectDeserializer derializer = this.derializers.get(type);获取
this.derializers也是一个map

 private final IdentityHashMap<Type, ObjectDeserializer> derializers      = new IdentityHashMap<Type, ObjectDeserializer>();

那么很简单了..我们只需要看看他默认添加了哪些类型的对象就可以了,那么这些类型也就是fastjson所支持的类型了...

接下来好像有那么点点....长....

但是好像发现了linkedHashMap的呻吟了啊...哦..是身影

 

    private ParserConfig(ASMDeserializerFactory asmFactory, ClassLoader parentClassLoader){
        if (asmFactory == null) {
            try {
                if (parentClassLoader == null) {
                    asmFactory = ASMDeserializerFactory.getInstance();    
                } else {
                    asmFactory = new ASMDeserializerFactory(parentClassLoader);
                }
            } catch (ExceptionInInitializerError error) {
                // skip
            } catch (AccessControlException error) {
                // skip
            } catch (NoClassDefFoundError error) {
                // skip
            }
        }
        
        this.asmFactory = asmFactory;
        
        if (asmFactory == null) {
            asmEnable = false;
        }
        
        primitiveClasses.add(boolean.class);
        primitiveClasses.add(Boolean.class);

        primitiveClasses.add(char.class);
        primitiveClasses.add(Character.class);

        primitiveClasses.add(byte.class);
        primitiveClasses.add(Byte.class);

        primitiveClasses.add(short.class);
        primitiveClasses.add(Short.class);

        primitiveClasses.add(int.class);
        primitiveClasses.add(Integer.class);

        primitiveClasses.add(long.class);
        primitiveClasses.add(Long.class);

        primitiveClasses.add(float.class);
        primitiveClasses.add(Float.class);

        primitiveClasses.add(double.class);
        primitiveClasses.add(Double.class);

        primitiveClasses.add(BigInteger.class);
        primitiveClasses.add(BigDecimal.class);

        primitiveClasses.add(String.class);
        primitiveClasses.add(java.util.Date.class);
        primitiveClasses.add(java.sql.Date.class);
        primitiveClasses.add(java.sql.Time.class);
        primitiveClasses.add(java.sql.Timestamp.class);

        derializers.put(SimpleDateFormat.class, DateFormatDeserializer.instance);
        derializers.put(java.sql.Timestamp.class, TimestampDeserializer.instance);
        derializers.put(java.sql.Date.class, SqlDateDeserializer.instance);
        derializers.put(java.sql.Time.class, TimeDeserializer.instance);
        derializers.put(java.util.Date.class, DateDeserializer.instance);
        derializers.put(Calendar.class, CalendarCodec.instance);

        derializers.put(JSONObject.class, JSONObjectDeserializer.instance);
        derializers.put(JSONArray.class, JSONArrayDeserializer.instance);

        derializers.put(Map.class, MapDeserializer.instance);
        derializers.put(HashMap.class, MapDeserializer.instance);
        derializers.put(LinkedHashMap.class, MapDeserializer.instance);
        derializers.put(TreeMap.class, MapDeserializer.instance);
        derializers.put(ConcurrentMap.class, MapDeserializer.instance);
        derializers.put(ConcurrentHashMap.class, MapDeserializer.instance);

        derializers.put(Collection.class, CollectionDeserializer.instance);
        derializers.put(List.class, CollectionDeserializer.instance);
        derializers.put(ArrayList.class, CollectionDeserializer.instance);

        derializers.put(Object.class, JavaObjectDeserializer.instance);
        derializers.put(String.class, StringCodec.instance);
        derializers.put(char.class, CharacterCodec.instance);
        derializers.put(Character.class, CharacterCodec.instance);
        derializers.put(byte.class, NumberDeserializer.instance);
        derializers.put(Byte.class, NumberDeserializer.instance);
        derializers.put(short.class, NumberDeserializer.instance);
        derializers.put(Short.class, NumberDeserializer.instance);
        derializers.put(int.class, IntegerCodec.instance);
        derializers.put(Integer.class, IntegerCodec.instance);
        derializers.put(long.class, LongCodec.instance);
        derializers.put(Long.class, LongCodec.instance);
        derializers.put(BigInteger.class, BigIntegerCodec.instance);
        derializers.put(BigDecimal.class, BigDecimalCodec.instance);
        derializers.put(float.class, FloatCodec.instance);
        derializers.put(Float.class, FloatCodec.instance);
        derializers.put(double.class, NumberDeserializer.instance);
        derializers.put(Double.class, NumberDeserializer.instance);
        derializers.put(boolean.class, BooleanCodec.instance);
        derializers.put(Boolean.class, BooleanCodec.instance);
        derializers.put(Class.class, ClassDerializer.instance);
        derializers.put(char[].class, CharArrayDeserializer.instance);

        derializers.put(AtomicBoolean.class, BooleanCodec.instance);
        derializers.put(AtomicInteger.class, IntegerCodec.instance);
        derializers.put(AtomicLong.class, LongCodec.instance);
        derializers.put(AtomicReference.class, ReferenceCodec.instance);

        derializers.put(WeakReference.class, ReferenceCodec.instance);
        derializers.put(SoftReference.class, ReferenceCodec.instance);

        derializers.put(UUID.class, UUIDCodec.instance);
        derializers.put(TimeZone.class, TimeZoneCodec.instance);
        derializers.put(Locale.class, LocaleCodec.instance);
        derializers.put(Currency.class, CurrencyCodec.instance);
        derializers.put(InetAddress.class, InetAddressCodec.instance);
        derializers.put(Inet4Address.class, InetAddressCodec.instance);
        derializers.put(Inet6Address.class, InetAddressCodec.instance);
        derializers.put(InetSocketAddress.class, InetSocketAddressCodec.instance);
        derializers.put(File.class, FileCodec.instance);
        derializers.put(URI.class, URICodec.instance);
        derializers.put(URL.class, URLCodec.instance);
        derializers.put(Pattern.class, PatternCodec.instance);
        derializers.put(Charset.class, CharsetCodec.instance);
        derializers.put(Number.class, NumberDeserializer.instance);
        derializers.put(AtomicIntegerArray.class, AtomicIntegerArrayCodec.instance);
        derializers.put(AtomicLongArray.class, AtomicLongArrayCodec.instance);
        derializers.put(StackTraceElement.class, StackTraceElementDeserializer.instance);

        derializers.put(Serializable.class, JavaObjectDeserializer.instance);
        derializers.put(Cloneable.class, JavaObjectDeserializer.instance);
        derializers.put(Comparable.class, JavaObjectDeserializer.instance);
        derializers.put(Closeable.class, JavaObjectDeserializer.instance);

        try {
            derializers.put(Class.forName("java.awt.Point"), PointCodec.instance);
            derializers.put(Class.forName("java.awt.Font"), FontCodec.instance);
            derializers.put(Class.forName("java.awt.Rectangle"), RectangleCodec.instance);
            derializers.put(Class.forName("java.awt.Color"), ColorCodec.instance);
        } catch (Throwable e) {
            // skip
        }
        
        try {
            derializers.put(Class.forName("java.time.LocalDateTime"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.LocalDate"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.LocalTime"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.ZonedDateTime"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.OffsetDateTime"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.OffsetTime"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.ZoneOffset"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.ZoneRegion"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.ZoneId"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.Period"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.Duration"), Jdk8DateCodec.instance);
            derializers.put(Class.forName("java.time.Instant"), Jdk8DateCodec.instance);
        } catch (Throwable e) {
            
        }
    }


另外我们看到提供了一个方法

    public void putDeserializer(Type type, ObjectDeserializer deserializer) {
        derializers.put(type, deserializer);
    }

也就是说不支持的类型亲可以自己去参考其它的写一个...好了..不BB了...结束

另外再提一下..

fastjson有几个构造函数,可以让你添加数据时是有序的:

    public JSONObject(Map<String, Object> map){
        this.map = map;
    }


    public JSONObject(boolean ordered){
        this(DEFAULT_INITIAL_CAPACITY, ordered);
    }

    public JSONObject(int initialCapacity, boolean ordered){
        if (ordered) {
            map = new LinkedHashMap<String, Object>(initialCapacity);
        } else {
            map = new HashMap<String, Object>(initialCapacity);
        }
    }

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值