加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 18:53:22 所属栏目:百科 来源:网络整理
导读:以前的fastjson我不清楚.. 而且这个问题网上好像没什么答案... so... 看了下源码,给各位提供个解决方案.. 解决方案主要有两种... 方案1:定义一个类继承TypeReferenceT T为LinkedHashMapString,Object 例如: import java.util.LinkedHashMap;import com.aliba

以前的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); } }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读