阿里fastjson注解@JSONField的使用

在开发过程中,我们经常会进行JSONObject对像和Java实体类对像的相互转换。使用场景无非下面三种:

Person转换为JSONObject

Person属性:值

---->

JSONObject属性:值

userName:zs

---->

userName:zs

userAge:18

---->

userAge:18

idNumber:1001

---->

idNumber:1001

JSONObject转换为Person(属性一致)

JSONObject属性:值

---->

Person属性:值

userName:zs

---->

userName:zs

userAge:18

---->

userAge:18

idNumber:1001

---->

idNumber:1001

JSONObject转换为Person(属性不一致)

JSONObject属性:值

---->

Person属性:值

name:zs

---->

userName:null

age:18

---->

userAge:null

idNumber:1001

---->

idNumber:1001

        对于前两种转换,我们不用额外考虑什么,直接转换就行了。但是对于第三种情况,即JSONObject对像里的属性名称和Person对像里的属性名称不一致,那么就会导致转换后的Person对像里userName和userAge的属性为null,这显然不是我们想要的结果。

      这种情况在实际开发中还是经常存在的,特别是在多系统、多数据源的情况下,通常我们约定的都是json格式的字符串,但是对json字符串里的字段名称等内容,却经常不可控。

    比方说,下划线命名(这种情况下,实际也可以正确给person对像赋值):

​​​​​​​{
    "user_age":"18",
    "user_name":"zhangsan",
    "id_number":"1001"
}

    比方说,奇怪的编码:

{
    "p001":"18",
    "p002":"zhangsan",
    "p003":"1001"
}

    这种情况下,再智能的工具也无法正确解析了,只会看到person的属性全部都是null。

    实际测试如下:

public static void main(String[] args) {
        String strA = "{\n" +
                "    \"user_age\":\"18\",\n" +
                "    \"user_name\":\"zhangsan\",\n" +
                "    \"id_number\":\"1001\"\n" +
                "}";
        JSONObject jsonObjectA = JSONObject.parseObject(strA);
        Person personA = JSON.parseObject(jsonObjectA.toJSONString(), Person.class);
        System.out.println("personA:  " + personA);

        String strB = "{\n" +
                "    \"P001\":\"18\",\n" +
                "    \"P002\":\"zhangsan\",\n" +
                "    \"P003\":\"1001\"\n" +
                "}";
        JSONObject jsonObjectB = JSONObject.parseObject(strB);
        Person personB = JSON.parseObject(jsonObjectB.toJSONString(), Person.class);
        System.out.println("personB:  " + personB);
    }

执行结果:

    那么,该如何解决呢?

    这个时候,注解@JSONField就派上用场了。@JSONField注解可以改变序列化和反序列化字段的名称。

    这个注解的源代码如下:

/*
 * Copyright 1999-2101 Alibaba Group.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.fastjson.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;

/**
 * @author wenshao[szujobs@hotmail.com]
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
public @interface JSONField {
    /**
     * config encode/decode ordinal
     * @since 1.1.42
     * @return
     */
    int ordinal() default 0;

    String name() default "";

    String format() default "";

    boolean serialize() default true;

    boolean deserialize() default true;

    SerializerFeature[] serialzeFeatures() default {};

    Feature[] parseFeatures() default {};
    
    String label() default "";
    
    /**
     * @since 1.2.12
     */
    boolean jsonDirect() default false;
    
    /**
     * Serializer class to use for serializing associated value.
     * 
     * @since 1.2.16
     */
    Class<?> serializeUsing() default Void.class;
    
    /**
     * Deserializer class to use for deserializing associated value. 
     * 
     * @since 1.2.16 
     */
    Class<?> deserializeUsing() default Void.class;

    /**
     * @since 1.2.21
     * @return the alternative names of the field when it is deserialized
     */
    String[] alternateNames() default {};
}

  可以看到,它可以用在方法上,类的成员变量上,方法中的参数上。

  用在字段上,如下:

package ztt.JSONFieldtest;

import com.alibaba.fastjson.annotation.JSONField;

/**
 * @date 20200728
 */
public class Person {
    @JSONField(name = "P001")
    private String userName;
    @JSONField(name = "P002")
    private String userAge;
    private String idNumber;

    

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserAge() {
        return userAge;
    }

    public void setUserAge(String userAge) {
        this.userAge = userAge;
    }

    public String getIdNumber() {
        return idNumber;
    }

    public void setIdNumber(String idNumber) {
        this.idNumber = idNumber;
    }

    @Override
    public String toString() {
        return "Person{" +
                "userName='" + userName + '\'' +
                ", userAge='" + userAge + '\'' +
                ", idNumber='" + idNumber + '\'' +
                '}';
    }
}

用在方法上,如下列所示:

@JSONField(name = "P001")
    public String getUserName() {
        return userName;
    }
    
    @JSONField(name = "P001")
    public void setUserName(String userName) {
        this.userName = userName;
    }

这个时候,我们再做对像之间的转换,如下图所示:

public static void main(String[] args) {
        String strB = "{\n" +
                "    \"P001\":\"18\",\n" +
                "    \"P002\":\"zhangsan\",\n" +
                "    \"idNumber\":\"1001\"\n" +
                "}";
        JSONObject jsonObjectB = JSONObject.parseObject(strB);
        Person personB = JSON.parseObject(jsonObjectB.toJSONString(), Person.class);
        System.out.println("personB:  " + personB);
    }

执行结果:

可以看到,json对像字符串属性名称和person对像属性不一致,也能正常转化了。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

架构帅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值