Spring MVCでは、FastJsonを使ってカスタムコメントを行います。
34301 ワード
最近はJavaに翻訳しています。その中で卵が痛い問題がありました。以前.net属性名はすべてイニシャルで大文字でした。クライアントに返信するJSON文字列の属性名はすべてイニシャル大文字となります。先端とドッキングするために、私達は以前は下図のようにしていました。
まず引き継ぎを使ったことがあります WebMvcConfigrationSupportクラスは、カスタムプロファイルクラスを実現します。
以下は2つのカスタムフィルタです。
属性名を扱う場合はNameFilterを継承します。
コードを修正しました。主にJSONFieldとの衝突を防止するためです。
属性の内容を扱う場合は継承します。 Value FilterはBigDecimalに数字を入れると、順序化して精度がなくなることがあります。 new Big Decimal(113.880)は、序文化されてからなりました。 113.87999999999999999999999999999999995264911353810248046875
個々に処理するのは面倒くさいです。この方式を設計しました。
以下は注釈部分です。
github接続を添付します。https://github.com/RaidenXin/FastJsonDemo/tree/master
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