代码改变世界

fastjson WriteClassName,Double类型不打3.3D

2017-12-21 20:16  Loull  阅读(894)  评论(0)    收藏  举报

方式一:

public class SerializeConfigX extends SerializeConfig {

    public SerializeConfigX() {
        put(Double.class, DoubleSerializerX.instance);
        put(Long.class, LongCodecX.instance);
    }

    static class DoubleSerializerX extends DoubleSerializer {

        public final static DoubleSerializerX instance = new DoubleSerializerX();

        @Override
        public void write(JSONSerializer serializer, Object object, Object fieldName,
                          Type fieldType, int features) throws IOException {
            SerializeWriter out = serializer.out;

            if (object == null) {
                out.writeNull(SerializerFeature.WriteNullNumberAsZero);
                return;
            }

            double doubleValue = ((Double) object).doubleValue();

            if (Double.isNaN(doubleValue) //
                || Double.isInfinite(doubleValue)) {
                out.writeNull();
            } else {
                out.writeDouble(doubleValue, false);
            }
        }
    }

    static class LongCodecX extends LongCodec {
        public static LongCodecX instance = new LongCodecX();

        @Override
        public void write(JSONSerializer serializer, Object object, Object fieldName,
                          Type fieldType, int features) throws IOException {
            SerializeWriter out = serializer.out;

            if (object == null) {
                out.writeNull(SerializerFeature.WriteNullNumberAsZero);
            } else {
                long value = ((Long) object).longValue();
                out.writeLong(value);
            }
        }
    }

}

 

方式二:

public class SerializeConfigX2 extends SerializeConfig {
    /** 
     * private的变量,只能重新定义一把,开销不大。 
     */
    private ASMSerializerFactory asmFactory;
    private boolean              asm = !ASMUtils.isAndroid();
    {
        try {
            asmFactory = new ASMSerializerFactory();
        } catch (NoClassDefFoundError eror) {
            asm = false;
        } catch (ExceptionInInitializerError error) {
            asm = false;
        }
    }

    @Override
    public ObjectSerializer createJavaBeanSerializer(Class<?> clazz) {
        if (!Modifier.isPublic(clazz.getModifiers())) {
            return new JavaBeanSerializerX(clazz);
        }

        boolean asm = this.asm;

        if (asm && asmFactory.isExternalClass(clazz) || clazz == Serializable.class
            || clazz == Object.class) {
            asm = false;
        }

        {
            JSONType annotation = clazz.getAnnotation(JSONType.class);
            if (annotation != null && annotation.asm() == false) {
                asm = false;
            }
        }

        if (asm && !ASMUtils.checkName(clazz.getName())) {
            asm = false;
        }

        if (asm) {
            try {
                ObjectSerializer asmSerializer = createASMSerializer(clazz);
                if (asmSerializer != null) {
                    return asmSerializer;
                }
            } catch (ClassCastException e) {
                // skip  
            } catch (Throwable e) {
                throw new JSONException("create asm serializer error, class " + clazz, e);
            }
        }

        return new JavaBeanSerializerX(clazz);
    }

    class JavaBeanSerializerX extends JavaBeanSerializer {
        public JavaBeanSerializerX(Class<?> clazz) {
            super(clazz);
        }

        @Override
        public FieldSerializer createFieldSerializer(FieldInfo fieldInfo) {
            Class<?> clazz = fieldInfo.getFieldClass();
            /** 
             * 修复android下的bug(非android下使用ASMSerializer,不报错)。 
             *  
             * 所有的努力都是为了这里,启用WriteClassName后,原生类型通过ObjectFieldSerializer( 
             * javabean反射)取得的值是对应的对象,json串会加上对应类型后缀(L、F、D、S、B)。 
             * 如果javabean使用原生类型定义变量,则反系列化parse时错误。 
             *  
             * 在此修复bug:原生类型务必使用NumberFieldSerializer 
             * (此类为包访问限制,只好复制一个NumberFieldSerializerX) 
             *  
             */
            if (clazz == Number.class || clazz == long.class || clazz == int.class
                || clazz == float.class || clazz == double.class || clazz == short.class
                || clazz == byte.class) {
                return new NumberFieldSerializerX(fieldInfo);
            }

            return super.createFieldSerializer(fieldInfo);
        }

    }

    /** 
     * copy NumberFieldSerializer 
     */
    class NumberFieldSerializerX extends FieldSerializer {

        public NumberFieldSerializerX(FieldInfo fieldInfo) {
            super(fieldInfo);
        }

        @Override
        public void writeProperty(JSONSerializer serializer,
                                  Object propertyValue) throws Exception {
            writePrefix(serializer);
            this.writeValue(serializer, propertyValue);
        }

        @Override
        public void writeValue(JSONSerializer serializer, Object propertyValue) throws Exception {
            SerializeWriter out = serializer.getWriter();

            Object value = propertyValue;

            if (value == null) {
                if (out.isEnabled(SerializerFeature.WriteNullNumberAsZero)) {
                    out.write('0');
                } else {
                    out.writeNull();
                }
                return;
            }

            out.append(value.toString());
        }
    }
}

 

main:

JSON.toJSONString(user, new SerializeConfigX(),
            SerializerFeature.WriteClassName, SerializerFeature.DisableCircularReferenceDetect);