关于数据序列化(5),定制FastJSON序列化(解决Java大Long类型js的Number接收丢失数据的问题,不序列化某些属性)

1. 指定某个类型序列化

问题描述:
JavaScript使用IEEE 754标准

1位用来表示符号位
11位用来表示指数
52位表示尾数

javaScript对于整形只能识别52位。遇到Long大整数可能会丢失数据
因为后台是Java写的难免有属性的类型是long。本来项目的做法是手动写每个类的toString();方法要拼接很多双引号。比较费劲也容易出错。
后来我使用了FastJson定制序列化遇到Long就写字符串来解决返回给客户端的JSON。
主要代码如下:

定制Long类型的序列化
    public final static SerializeConfig resultJsonConfig = new SerializeConfig();
    static{
        resultJsonConfig.put(Long.class, new ObjectSerializer() {
            @Override
            public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
                    throws IOException {
                SerializeWriter out = serializer.getWriter();
                out.writeString(Objects.toString(object, null));
            }
        });
    }

使用:
    protected <T> String getResult(T value) {
        JSONObject json = new JSONObject();
        json.put("state", state.getState());
        json.put("desc", state.getDesc());
        json.put("value", value);
        return JSON.toJSONString(json, resultJsonConfig, SerializerFeature.DisableCircularReferenceDetect);
    }
2.如果要让这个策略全局生效
SerializeConfig.getGlobalInstance().put(Long.class, new ObjectSerializer() {
            @Override
            public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
                    throws IOException {
                SerializeWriter out = serializer.getWriter();

                if (fieldType == long.class || fieldType == Long.class) {
                    out.writeString(Objects.toString(object, null));
                }
                // if (numberValue == null) {
                // if (out.isEnabled(SerializerFeature.WriteNullNumberAsZero)) {
                // out.write('0');
                // } else {
                // out.writeNull();
                // }
                // return;
                // }

            }
        });

2. 对某些属性不序列化

2.1 定义一个注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface ResultNotSerialize {

}
2.2 将注解加在属性上
public class MemberVO {
    private String memberId;
    private String memberName;

    @ResultNotSerialize
    private String password;
2.3 定义一个过滤器
    public static final PropertyFilter controllerResultJsonFilter = new PropertyFilter() {
        @Override
        public boolean apply(Object object, String key, Object value) {
            try {
                Field field = object.getClass().getDeclaredField(key);
                if(null !=field && null != field.getAnnotation(ResultNotSerialize.class)){
                    return false;
                }
                return true;
            } catch (Exception e) {
                return true;
            }
        }
    };
2.4 如何使用
SON.toJSONString(obj, controllerResultJsonFilter);

3. Java长ID,js接收丢失数据问题最终的解决办法

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface SerializeAsSting {

}
public class MemberVO {
    @SerializeAsSting
    private Long id = 0L;//long type id
 public static final PropertyFilter resultJsonPropertyFilter = new PropertyFilter() {
        @Override
        public boolean apply(Object object, String key, Object value) {
            try {
                Field field = object.getClass().getDeclaredField(key);
                if (null != field && null != field.getAnnotation(NotSerialize.class)) {
                    return false;
                }
                return true;
            } catch (Exception e) {
                return true;
            }
        }
    };

    public static final ValueFilter resultValueFilter = new ValueFilter() {
        @Override
        public Object process(Object object, String name, Object value) {
//          LogCore.BASE.info("object={}, name={},value={}", object, name, value);
            if(value == null){
                return value;
            }
            try {
                Field field = object.getClass().getDeclaredField(name);
                if (null != field && null != field.getAnnotation(SerializeAsSting.class)) {
                    return value.toString();
                }
                return value;
            } catch (Exception e) {
                return value;
            }
        }
    };
    public final static SerializeFilter[] resultJsonFilters = new SerializeFilter[]{resultJsonPropertyFilter, resultValueFilter};
protected <T> String getResult(ErrorState state, T value) {
        JSONObject json = new JSONObject();
        json.put("state", state.getState());
        json.put("desc", state.getDesc());
        json.put("value", value);
        return JSON.toJSONString(json, resultJsonConfig, resultJsonFilters,
                SerializerFeature.WriteMapNullValue, SerializerFeature.DisableCircularReferenceDetect);
    }

其他的序列化见这篇文章fastjson使用@JSONField、@JSONType、SerializeFilter定制序列化

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java中的Fastjson库提供了一种方便的方式来进行JSON序列化和反序列化操作。要使用Fastjson进行反序列化,你需要按照以下步骤进行操作: 1. 首先,确保你已经将Fastjson库添加到你的项目中。你可以通过Maven或者手动下载并导入jar文件来添加依赖。 2. 创建一个Java类,该类的结构应该与你要反序列化JSON数据的结构相匹配。 3. 导入Fastjson的相关类,包括JSON和JSONObject。 4. 使用JSON类的parseObject()方法将JSON字符串转换为JSONObject对象。 5. 使用JSONObject对象的toJavaObject()方法将JSONObject转换为你定义的Java类对象。 下面是一个简单的示例代码,演示了如何使用Fastjson进行反序列化: ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; public class Main { public static void main(String[] args) { // JSON数据 String jsonString = "{\"name\":\"John\",\"age\":30}"; // 将JSON字符串转换为JSONObject对象 JSONObject jsonObject = JSON.parseObject(jsonString); // 将JSONObject对象转换为Java对象 Person person = jsonObject.toJavaObject(Person.class); // 打印Java对象的属性值 System.out.println("Name: " + person.getName()); System.out.println("Age: " + person.getAge()); } } class Person { private String name; private int age; // 省略getter和setter方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } ``` 在上面的示例中,我们首先将JSON字符串转换为JSONObject对象,然后将JSONObject对象转换为Person类的实例。最后,我们可以通过调用Person对象的getter方法来获取属性值。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值