zoukankan      html  css  js  c++  java
  • Fastjson处理枚举

    Fastjson

    这玩意儿不多说,Alibaba出品,出过几次严重的安全漏洞,但是依然很流行。这里写一下它怎么处理枚举。

    <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.76</version>
    </dependency>
    

    序列化为name()值

    默认就是,啥也不用动

    import com.alibaba.fastjson.JSON;
    
    enum Gender {
    	BOY, GIRL, UNKNOW
    }
    
    class User {
    	private Integer id;
    	private Gender gender;
    	public User() {
    	}
    	public User(Integer id, Gender gender) {
    		super();
    		this.id = id;
    		this.gender = gender;
    	}
    
    	public Integer getId() {
    		return id;
    	}
    
    	public void setId(Integer id) {
    		this.id = id;
    	}
    
    	public Gender getGender() {
    		return gender;
    	}
    
    	public void setGender(Gender gender) {
    		this.gender = gender;
    	}
    }
    
    public class MainTest {
    
    	public static void main(String[] args) throws Exception {
    		
    		// 序列化为JSON输出
    		User user = new User(1, Gender.BOY);
    		String jsonString = JSON.toJSONString(user); 
    		System.out.println(jsonString);	// {"gender":"BOY","id":1}
    		
    		
    		// 反序列化为对象
    		user = JSON.parseObject(jsonString, User.class);
    		System.out.println(user.getGender());		// BOY
    	}
    }
    

    序列化为ordinal()值

    全局设置

    代码跟上面没有变化,就需要在开头添加一句代码,任何枚举,都会被序列化为ordinal()值

    JSON.DEFAULT_GENERATE_FEATURE &= ~SerializerFeature.WriteEnumUsingName.mask;
    
    		// 全局设置,枚举的序列化使用 ordinal()
    		JSON.DEFAULT_GENERATE_FEATURE &= ~SerializerFeature.WriteEnumUsingName.mask;
    		
    		// 序列化为JSON输出,枚举值为 ordinal()
    		User user = new User(1, Gender.BOY);
    		String jsonString = JSON.toJSONString(user); 
    		System.out.println(jsonString);	// {"gender":0,"id":1}
    		
    		
    		// 反序列化为对象
    		user = JSON.parseObject(jsonString, User.class);
    		System.out.println(user.getGender());		// BOY
    

    特殊设置

    只想针对某一次序列化生效。只需要调用JSON.toJSONString的重载方法,添加配置就行。

    public static String toJSONString(Object object, int defaultFeatures, SerializerFeature... features)
    
    		// 序列化为JSON输出,本次把枚举值序列化为 ordinal()
    		User user = new User(1, Gender.BOY);
    		String jsonString = JSON.toJSONString(user, JSON.DEFAULT_GENERATE_FEATURE & ~SerializerFeature.WriteEnumUsingName.mask); 
    		System.out.println(jsonString);	// {"gender":0,"id":1}
    		
    		
    		// 反序列化为对象
    		user = JSON.parseObject(jsonString, User.class);
    		System.out.println(user.getGender());		// BOY
    

    序列化为自定义属性

    很多人也喜欢给枚举定义一个私有的属性,序列化为JSON时,希望以这个属性值作为value,这个时候就需要自己定义JSON的序列化和反序列化实现了。Fastjson提供了2个接口。用户控制序列化和反序列化行为,这个实在是太简单,这里不多说。看代码

    • ObjectSerializer
    • ObjectDeserializer

    序列化器的定义

    import java.io.IOException;
    import java.lang.reflect.Type;
    
    import com.alibaba.fastjson.serializer.JSONSerializer;
    import com.alibaba.fastjson.serializer.ObjectSerializer;
    
    public class GenderEnumSerializer implements ObjectSerializer {
    	@Override
    	public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
    		// 强制把值转换为Gender
    		Gender gender = (Gender) object;
    		// 序列化为自定义的name属性,输出就行
    		serializer.out.writeString(gender.getName());
    	}
    }
    

    反序列化器的定义

    import java.lang.reflect.Type;
    
    import com.alibaba.fastjson.parser.DefaultJSONParser;
    import com.alibaba.fastjson.parser.JSONToken;
    import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
    
    public class GenderEnumDeserializer implements ObjectDeserializer {
    	@SuppressWarnings("unchecked")
    	@Override
    	public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
    		// 解析值为字符串
    		String value = parser.parseObject(String.class);
    		// 遍历所有的枚举实例
    		for (Gender gender : Gender.values()) {
    			if (gender.getName().equals(value)) {
    				// 成功匹配,返回实例
    				return (T) gender;
    			}
    		}
    		// 没有匹配到,可以抛出异常或者返回null
    		return null;
    	}
    
    	@Override
    	public int getFastMatchToken() {
    		// 仅仅匹配字符串类型的值
    		return JSONToken.LITERAL_STRING;
    	}
    }
    

    对象 & 枚举的定义

    enum Gender {
    	
    	BOY("男"), GIRL("女"), UNKNOW("不知道");
    	
    	public final String name;
    	
    	Gender(String name) {
    		this.name = name;
    	}
    	public String getName() {
    		return name;
    	}
    }
    
    
    class User {
    	
    	private Integer id;
    	
    	// 标识注解,指定枚举的序列化。反序列化实现类
    	@JSONField(serializeUsing = GenderEnumSerializer.class, deserializeUsing = GenderEnumDeserializer.class)
    	private Gender gender;
    
    	public User() {
    	}
    
    	public User(Integer id, Gender gender) {
    		super();
    		this.id = id;
    		this.gender = gender;
    	}
    
    	public Integer getId() {
    		return id;
    	}
    
    	public void setId(Integer id) {
    		this.id = id;
    	}
    
    	public Gender getGender() {
    		return gender;
    	}
    
    	public void setGender(Gender gender) {
    		this.gender = gender;
    	}
    }
    

    测试

    public class MainTest {
    
    	public static void main(String[] args) throws Exception {
    
    		// 序列化为JSON输出,枚举值为 getName()
    		User user = new User(1, Gender.UNKNOW);
    		String jsonString = JSON.toJSONString(user);
    		System.out.println(jsonString); // {"gender":"不知道","id":1}
    
    		// 反序列化为对象
    		user = JSON.parseObject(jsonString, User.class);
    		System.out.println(user.getGender()); // UNKNOW
    	}
    }
    

    最后

    很显然,自定义 ObjectSerializer /ObjectDeserializer 的方式最为灵活,可以考虑抽象一个接口出来,让所有的枚举都实现接口。这样针对接口编写ObjectSerializer /ObjectDeserializer实现,就可以很好的复用了。


    本文首发:https://springboot.io/t/topic/3648

  • 相关阅读:
    BEC listen and translation exercise 44
    中译英12
    BEC listen and translation exercise 43
    中译英11
    BEC listen and translation exercise 42
    中译英10
    BEC listen and translation exercise 41
    中译英9
    BEC listen and translation exercise 40
    中译英8
  • 原文地址:https://www.cnblogs.com/kevinblandy/p/14758000.html
Copyright © 2011-2022 走看看