Spring MVCでは、FastJsonを使ってカスタムコメントを行います。

34301 ワード

最近はJavaに翻訳しています。その中で卵が痛い問題がありました。以前.net属性名はすべてイニシャルで大文字でした。クライアントに返信するJSON文字列の属性名はすべてイニシャル大文字となります。先端とドッキングするために、私達は以前は下図のようにしていました。
public class User {

    @JSONField(name = "Name")
    private String name;
    @JSONField(name = "Age")
    private BigDecimal age;
    @JSONField(name = "Id")
    private String id;
    @JSONField(name = "isGirl")
    private boolean girl;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public BigDecimal getAge() {
        return age;
    }

    public void setAge(BigDecimal age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isGirl() {
        return girl;
    }

    public void setGirl(boolean girl) {
        this.girl = girl;
    }
}
各属性にJSONFieldを加えて属性名を定義します。特に煩雑で間違いやすいです。次はFastJsonのカスタムコメントを使って、一つの注釈で実現します。
まず引き継ぎを使ったことがあります WebMvcConfigrationSupportクラスは、カスタムプロファイルクラスを実現します。
package com.raiden;

import com.alibaba.fastjson.serializer.SerializeFilter;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.raiden.filter.DataToStringFilter;
import com.raiden.filter.FirstLetterCapitalizedFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.util.List;

@Configuration
public class ExtWebMvcConfigurerAdapter extends WebMvcConfigurationSupport {

    protected void configureMessageConverters(List> converters) {
        //new         
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonMessageConverter();
        //       2         
        SerializeFilter[] filters = {new FirstLetterCapitalizedFilter(), new DataToStringFilter()};
        //              
        fastJsonHttpMessageConverter.getFastJsonConfig().setSerializeFilters(filters);
        //           
        converters.add(fastJsonHttpMessageConverter);
        //             
        super.configureMessageConverters(converters);
    }
}
以下はカスタム変換器です。実は簡単です。何もしなくてもいいです。簡単に続けばいいです。
package com.raiden;

import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;

/**
 *      
 */
public class FastJsonMessageConverter extends FastJsonHttpMessageConverter {

}
 
以下は2つのカスタムフィルタです。
属性名を扱う場合はNameFilterを継承します。
コードを修正しました。主にJSONFieldとの衝突を防止するためです。
 
package com.raiden.fastjson.filter;

import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.NameFilter;
import com.raiden.fastjson.util.FieldNameUtils;
import com.raiden.fastjson.annotation.FirstLetterCapitalized;
import com.raiden.fastjson.annotation.Ignore;
import com.raiden.fastjson.util.FieldUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;

/**
 * @   :Raiden
 * @Descriotion:         ,        
 * @Date:Created in 9:54 2019/6/22
 * @Modified By:
 */
public class FirstLetterCapitalizedFilter implements NameFilter {
    @Override
    public String process(Object instance, String name, Object value) {
        if (null == instance || StringUtils.isEmpty(name)){
            return name;
        }
        Class> clazz = instance.getClass();
        //               
        if (clazz.isAnnotationPresent(FirstLetterCapitalized.class)){
            //   boolean  
            boolean isBooleanInstance = Boolean.class.isInstance(value);
            //              JSONField              
            Field field = FieldUtils.getField(clazz, name);
            if (null != field){
                //             JSONField                         
                if (field.isAnnotationPresent(Ignore.class) || field.isAnnotationPresent(JSONField.class)){
                    return name;
                }else{
                    //              name   is               is
                    if (isBooleanInstance && !name.toLowerCase().startsWith("is")){
                        return "Is" + FieldNameUtils.firstLetterCapitalized(name);
                    }
                    //           
                    return FieldNameUtils.firstLetterCapitalized(name);
                }
            }
            // JSONField                                 
            return checkBoolean(clazz, name, isBooleanInstance);
        }
        return name;
    }

    private String checkBoolean(Class> clazz, String name,boolean isBooleanInstance){
        if (isBooleanInstance){
            //          2   1   JSONField   2        is     isShow    name  show
            String fieldName = "is" + FieldNameUtils.firstLetterCapitalized(name);
            //                 
            Field field = FieldUtils.getField(clazz, fieldName);
            //         is 
            if (null != field){
                return fieldName;
            }
        }
        //               JSONField  
        return name;
    }
}
 
 
属性の内容を扱う場合は継承します。 Value FilterはBigDecimalに数字を入れると、順序化して精度がなくなることがあります。  new Big Decimal(113.880)は、序文化されてからなりました。 113.87999999999999999999999999999999995264911353810248046875
個々に処理するのは面倒くさいです。この方式を設計しました。
 
package com.raiden.fastjson.filter;

import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.raiden.fastjson.util.FieldNameUtils;
import com.raiden.fastjson.annotation.DataToString;
import com.raiden.fastjson.annotation.FirstLetterCapitalized;
import com.raiden.fastjson.util.FieldUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
/**
 * @   :Raiden
 * @Descriotion:   BigDecimal   ,        
 * @Date:Created in 9:54 2019/6/22
 * @Modified By:
 */
public class DataToStringFilter implements ValueFilter {
    @Override
    public Object process(Object instance, String name, Object value) {
        if (null == instance || StringUtils.isEmpty(name) || null == value){
            return value;
        }
        //        BigDecimal     Double
        if (value instanceof Double || value instanceof BigDecimal){
            Class> instanceClazz = instance.getClass();
            //                 
            if (instanceClazz.isAnnotationPresent(FirstLetterCapitalized.class)){
                name = FieldNameUtils.firstLetterLowercase(name);
            }
            //              JSONField                
            Field field = FieldUtils.getField(instanceClazz, name);
            if (null == field){
                field = getField(instanceClazz, name);
            }
            //        DataToString  
            if (null != field && field.isAnnotationPresent(DataToString.class)){
                return valueFormat(value, field);
            }
        }
        return value;
    }

    /**
     *      
     * @param value
     * @param field
     * @return
     */
    private Object valueFormat(Object value,Field field){
        //  DataToString  
        DataToString dataToString = field.getAnnotation(DataToString.class);
        //       
        int newScale = dataToString.newScale();
        //      
        int roundingMode = dataToString.roundingMode();
        if (value instanceof Double){
            return new BigDecimal((Double) value).setScale(newScale, roundingMode).toString();
        }
        //     
        return ((BigDecimal) value).setScale(newScale, roundingMode).toString();
    }

    /**
     *        
     * @param instanceClazz
     * @param name
     * @return
     */
    private Field getField(Class> instanceClazz,String name){
        Class> superclass = instanceClazz.getSuperclass();
        if (null == superclass){
            //         Object        
            return null;
        }
        //      
        Field[] fields = instanceClazz.getDeclaredFields();
        for (Field field : fields){
            if (!field.isAnnotationPresent(JSONField.class)){
                continue;
            }
            JSONField jsonField = field.getAnnotation(JSONField.class);
            if (name.equals(jsonField.name())){return field;
            }
        }
        return getField(superclass, name);
    }
}
 
       :
package com.raiden.fastjson;

/**
 * @   :Raiden
 * @Descriotion:        
 * @Date:Created in 21:26 2019/6/23
 * @Modified By:
 */
public class FieldNameUtils {

    /**
     *         
     * @param name
     * @return
     */
    public static String firstLetterCapitalized(String name){
        char[] chars = name.toCharArray();
        StringBuilder builder = new StringBuilder();
        char c = chars[0];
        //        
        if (c > 96 && c < 123){
            c -= 32;
            chars[0] = c;

        }
        builder.append(chars);
        return builder.toString();
    }

    /**
     *      
     * @param name
     * @return
     */
    public static String firstLetterLowercase(String name){
        char[] chars = name.toCharArray();
        StringBuilder builder = new StringBuilder();
        char c = chars[0];
        //        
        if (c > 64 && c < 91){
            c += 32;
            chars[0] = c;

        }
        builder.append(chars);
        return builder.toString();
    }
}
 
package com.raiden.fastjson.util;

import java.lang.reflect.Field;

/**
 * @   :Raiden
 * @Descriotion:
 * @Date:Created in 23:11 2019/7/4
 * @Modified By:
 */
public class FieldUtils {

    /**
     *                          Object  
     * @param clazz
     * @param fieldName
     * @return
     */
    public static Field getField(Class> clazz, String fieldName){
        //    class
        Class> superclass = clazz.getSuperclass();
        if (null == superclass){
            //         Object        
            return null;
        }
        Field declaredField = null;
        try {
            //    
            declaredField = clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            //           
            return getField(superclass, fieldName);
        }
        //     
        return declaredField;
    }
}
 
以下は注釈部分です。
package com.raiden.annotation;

import java.lang.annotation.*;

/**
 *         FastJson                  
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FirstLetterCapitalized {
}
package com.raiden.annotation;

import java.lang.annotation.*;
import java.math.BigDecimal;

/**
 *     BigDecimal       
 *  BigDecimal  String
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DataToString {
    //    3   
    int newScale() default 3;
    //        
    int roundingMode() default BigDecimal.ROUND_HALF_UP;
}
package com.raiden.annotation;

import java.lang.annotation.*;

/**
 *        
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Ignore {
}
テストコード:
package com.raiden.controller;

import com.raiden.model.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;

@RestController
public class UserController {

    @GetMapping("getUser")
    public User getUser(){
        User user = new User();
        user.setId("1");
        user.setName("zhangsan");
        user.setAge(new BigDecimal(113.880));
        return user;
    }
}
package com.raiden.model;

import com.alibaba.fastjson.annotation.JSONField;
import com.raiden.annotation.DataToString;
import com.raiden.annotation.FirstLetterCapitalized;
import com.raiden.annotation.Ignore;
import com.raiden.annotation.Range;

import java.math.BigDecimal;

@FirstLetterCapitalized
public class User {

    @Ignore
    private String name;
    @DataToString(newScale = 3,roundingMode = BigDecimal.ROUND_HALF_UP)
    private BigDecimal age;
    @JSONField(name = "userId")
    private String id;
    private boolean girl;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public BigDecimal getAge() {
        return age;
    }

    public void setAge(BigDecimal age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isGirl() {
        return girl;
    }

    public void setGirl(boolean girl) {
        this.girl = girl;
    }
}
package com.raiden;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {

    public static void main(String[] arg){
        SpringApplication.run(App.class, arg);
    }
}
初めてブログを書きますが、何か問題がありましたら、ご指摘をお願いします。コードは何度も修正されていますが、走れないならGitHubに行ってコードをダウンロードしてもいいです。ありがとうございます。
github接続を添付します。https://github.com/RaidenXin/FastJsonDemo/tree/master