Fastjson processing enumeration

Time:2021-8-30

Fastjson

Not much about this thing. Alibaba has produced several serious security vulnerabilities, but it is still very popular. Here’s how it handles enumeration.

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

Serialize to name() value

The default is, don’t move anything

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 {
        
        //Serialize to JSON output
        User user = new User(1, Gender.BOY);
        String jsonString = JSON.toJSONString(user); 
        System.out.println(jsonString);    // {"gender":"BOY","id":1}
        
        
        //Deserialize to object
        user = JSON.parseObject(jsonString, User.class);
        System.out.println(user.getGender());        // BOY
    }
}

Serialize to ordinal() value

Global settings

If the code is the same as the above, you need to add a code at the beginning. Any enumeration will be serialized into the ordinal () value

JSON.DEFAULT_GENERATE_FEATURE &= ~SerializerFeature.WriteEnumUsingName.mask;
//Global setting, the serialization of enumeration uses ordinal()
        JSON.DEFAULT_GENERATE_FEATURE &= ~SerializerFeature.WriteEnumUsingName.mask;
        
        //Serialize to JSON output, and the enumeration value is ordinal ()
        User user = new User(1, Gender.BOY);
        String jsonString = JSON.toJSONString(user); 
        System.out.println(jsonString);    // {"gender":0,"id":1}
        
        
        //Deserialize to object
        user = JSON.parseObject(jsonString, User.class);
        System.out.println(user.getGender());        // BOY

Special settings

Just want to take effect for one serialization. Just callJSON.toJSONStringOverloaded method, add configuration on the line.

public static String toJSONString(Object object, int defaultFeatures, SerializerFeature... features)
//Serialize to JSON output. This time, serialize the enumeration value to 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}
        
        
        //Deserialize to object
        user = JSON.parseObject(jsonString, User.class);
        System.out.println(user.getGender());        // BOY

Serialize as custom attribute

Many people also like to define a private attribute for enumeration. When serializing to JSON, they want to take this attribute value as value. At this time, they need to define their own serialization and deserialization implementation of JSON. Fastjson provides two interfaces. The user controls the serialization and deserialization behavior, which is too simple to say here. Look at the code

  • ObjectSerializer
  • ObjectDeserializer

Definition of serializer

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 {
        //Force value to gender
        Gender gender = (Gender) object;
        //Serialize it into a custom name attribute, and output it
        serializer.out.writeString(gender.getName());
    }
}

Definition of deserializer

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) {
        //Parse value to string
        String value = parser.parseObject(String.class);
        //Traverse all enumerated instances
        for (Gender gender : Gender.values()) {
            if (gender.getName().equals(value)) {
                //Successful matching, return instance
                return (T) gender;
            }
        }
        //If there is no match, you can throw an exception or return null
        return null;
    }

    @Override
    public int getFastMatchToken() {
        //Matches only values of string type
        return JSONToken.LITERAL_STRING;
    }
}

Definition of object & enumeration

enum Gender {
    
    Boy ("male"), girl ("female"), unknown ("unknown");
    
    public final String name;
    
    Gender(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}


class User {
    
    private Integer id;
    
    //Identifies the annotation that specifies the serialization of the enumeration. Deserialization implementation class
    @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;
    }
}

test

public class MainTest {

    public static void main(String[] args) throws Exception {

        //Serialize to JSON output, and the enumeration value is getname()
        User user = new User(1, Gender.UNKNOW);
        String jsonString = JSON.toJSONString(user);
        System.out.println(jsonString); // {" Gender ":" don't know "," Id ": 1}

        //Deserialize to object
        user = JSON.parseObject(jsonString, User.class);
        System.out.println(user.getGender()); // UNKNOW
    }
}

last

Obviously, the method of customizing objectserializer / objectdeserializer is the most flexible. You can consider abstracting an interface to make all enumerations implement the interface. In this way, the implementation of objectserializer / objectdeserializer for the interface can be reused.


This article starts:https://springboot.io/t/topic…