Java 如何实现JSON 的多态序列化?

新手上路,请多包涵

通过 SpringMVC 调用接口时会自动对返回结果进行多态序列化,但是我自己使用 fastjson 和 gson 的时候并不会进行多态序列化,想问下大佬们,我应该怎么实现 Java 对象的多态序列化?

喜欢能用代码展示

阅读 660
avatarAI BotBETA

在 Java 中实现 JSON 的多态序列化确实需要一些额外的配置,特别是对于像 fastjsongson 这样的库。下面是针对这两个库的解决方案。

使用 fastjson 实现多态序列化

fastjson 提供了 @JSONType 注解来处理多态序列化。你需要指定 @JSONType(reference = YourBaseClass.class) 注解在你的子类上,并且需要在父类上使用 @TypeName 注解来指定类型名称。

以下是一个示例:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONType;
import com.alibaba.fastjson.annotation.TypeName;

@TypeName("animal")
class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    // getters and setters
}

@JSONType(reference = Animal.class)
class Dog extends Animal {
    private String breed;

    public Dog(String name, String breed) {
        super(name);
        this.breed = breed;
    }

    // getters and setters
}

@JSONType(reference = Animal.class)
class Cat extends Animal {
    private boolean isScratchy;

    public Cat(String name, boolean isScratchy) {
        super(name);
        this.isScratchy = isScratchy;
    }

    // getters and setters
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog("Buddy", "Golden Retriever");
        Animal cat = new Cat("Whiskers", true);

        String dogJson = JSON.toJSONString(dog, SerializerFeature.PrettyFormat);
        String catJson = JSON.toJSONString(cat, SerializerFeature.PrettyFormat);

        System.out.println("Dog JSON: " + dogJson);
        System.out.println("Cat JSON: " + catJson);
    }
}

在这个例子中,DogCat 类都使用了 @JSONType(reference = Animal.class) 注解,而 Animal 类使用了 @TypeName("animal") 注解。这允许 fastjson 在序列化时正确处理多态。

使用 gson 实现多态序列化

gson 处理多态序列化稍微复杂一些,你需要使用 RuntimeTypeAdapterFactory。以下是一个示例:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.typeadapters.RuntimeTypeAdapterFactory;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    // getters and setters
}

class Dog extends Animal {
    private String breed;

    public Dog(String name, String breed) {
        super(name);
        this.breed = breed;
    }

    // getters and setters
}

class Cat extends Animal {
    private boolean isScratchy;

    public Cat(String name, boolean isScratchy) {
        super(name);
        this.isScratchy = isScratchy;
    }

    // getters and setters
}

public class Main {
    public static void main(String[] args) {
        Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(RuntimeTypeAdapterFactory.of(Animal.class)
                        .registerSubtype(Dog.class)
                        .registerSubtype(Cat.class))
                .create();

        Animal dog = new Dog("Buddy", "Golden Retriever");
        Animal cat = new Cat("Whiskers", true);

        String dogJson = gson.toJson(dog);
        String catJson = gson.toJson(cat);

        System.out.println("Dog JSON: " + dogJson);
        System.out.println("Cat JSON: " + catJson);
    }
}

在这个例子中,我们使用 RuntimeTypeAdapterFactory 来注册 Animal 的子类型 DogCat。这允许 gson 在序列化时正确处理多态。

这两种方法都可以帮助你实现 Java 对象的多态序列化。根据你的具体需求选择合适的库和方法。

1 个回答

1.创建基类和注解

BasePolymorphicObject.java

package com.example.serialization;

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface JsonTypeName {
    String value();
}

public abstract class BasePolymorphicObject {
    private String type;

    public BasePolymorphicObject() {
        JsonTypeName annotation = this.getClass().getAnnotation(JsonTypeName.class);
        if (annotation != null) {
            this.type = annotation.value();
        } else {
            this.type = this.getClass().getSimpleName();
        }
    }

    public String getType() {
        return type;
    }
}

2.创建序列化工具类

PolymorphicSerializationUtil.java

package com.example.serialization;

import com.google.gson.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializeConfig;

import java.util.HashMap;
import java.util.Map;

public class PolymorphicSerializationUtil {
    private static final Map<String, Class<? extends BasePolymorphicObject>> TYPE_MAP = new HashMap<>();
    private static final Gson gson;
    private static final ParserConfig fastjsonConfig;

    static {
        // 初始化Gson
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(BasePolymorphicObject.class, new JsonDeserializer<BasePolymorphicObject>() {
            @Override
            public BasePolymorphicObject deserialize(JsonElement json, java.lang.reflect.Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                JsonObject jsonObject = json.getAsJsonObject();
                String type = jsonObject.get("type").getAsString();
                Class<? extends BasePolymorphicObject> clazz = TYPE_MAP.get(type);
                if (clazz == null) {
                    throw new JsonParseException("Unknown type: " + type);
                }
                return context.deserialize(json, clazz);
            }
        });
        gson = gsonBuilder.create();

        // 初始化Fastjson
        fastjsonConfig = new ParserConfig();
        fastjsonConfig.setAutoTypeSupport(true);
    }

    // 注册类型
    public static void registerType(Class<? extends BasePolymorphicObject> clazz) {
        JsonTypeName annotation = clazz.getAnnotation(JsonTypeName.class);
        String type = annotation != null ? annotation.value() : clazz.getSimpleName();
        TYPE_MAP.put(type, clazz);
    }

    // Gson序列化
    public static String toJsonWithGson(BasePolymorphicObject obj) {
        try {
            return gson.toJson(obj, BasePolymorphicObject.class);
        } catch (Exception e) {
            throw new SerializationException("Failed to serialize object with Gson", e);
        }
    }

    // Gson反序列化
    public static <T extends BasePolymorphicObject> T fromJsonWithGson(String json, Class<T> expectedType) {
        try {
            BasePolymorphicObject obj = gson.fromJson(json, BasePolymorphicObject.class);
            if (!expectedType.isInstance(obj)) {
                throw new SerializationException("Deserialized object is not of expected type: " + expectedType.getSimpleName());
            }
            return expectedType.cast(obj);
        } catch (Exception e) {
            throw new SerializationException("Failed to deserialize JSON with Gson", e);
        }
    }

    // Fastjson序列化
    public static String toJsonWithFastjson(BasePolymorphicObject obj) {
        try {
            SerializeConfig config = new SerializeConfig();
            return JSON.toJSONString(obj, config);
        } catch (Exception e) {
            throw new SerializationException("Failed to serialize object with Fastjson", e);
        }
    }

    // Fastjson反序列化
    public static <T extends BasePolymorphicObject> T fromJsonWithFastjson(String json, Class<T> expectedType) {
        try {
            Object obj = JSON.parseObject(json, BasePolymorphicObject.class, fastjsonConfig);
            if (!expectedType.isInstance(obj)) {
                throw new SerializationException("Deserialized object is not of expected type: " + expectedType.getSimpleName());
            }
            return expectedType.cast(obj);
        } catch (Exception e) {
            throw new SerializationException("Failed to deserialize JSON with Fastjson", e);
        }
    }
}

3.自定义异常类

SerializationException.java

package com.example.serialization;

public class SerializationException extends RuntimeException {
    public SerializationException(String message) {
        super(message);
    }

    public SerializationException(String message, Throwable cause) {
        super(message, cause);
    }
}

4.示例使用

Dog.java

package com.example.serialization;

@JsonTypeName("dog")
public class Dog extends BasePolymorphicObject {
    private String name;
    private int age;

    public Dog(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    // Getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

Cat.java

package com.example.serialization;

@JsonTypeName("cat")
public class Cat extends BasePolymorphicObject {
    private String name;
    private String color;

    public Cat(String name, String color) {
        super();
        this.name = name;
        this.color = color;
    }

    // Getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getColor() { return color; }
    public void setColor(String color) { this.color = color; }
}

Example.java

package com.example.serialization;

public class Example {
    public static void main(String[] args) {
        try {
            // 注册类型
            PolymorphicSerializationUtil.registerType(Dog.class);
            PolymorphicSerializationUtil.registerType(Cat.class);

            // 创建对象
            Dog dog = new Dog("Buddy", 3);
            Cat cat = new Cat("Whiskers", "gray");

            // Gson序列化示例
            String dogJson = PolymorphicSerializationUtil.toJsonWithGson(dog);
            String catJson = PolymorphicSerializationUtil.toJsonWithGson(cat);

            System.out.println("Dog JSON: " + dogJson);
            System.out.println("Cat JSON: " + catJson);

            // Gson反序列化示例
            Dog deserializedDog = PolymorphicSerializationUtil.fromJsonWithGson(dogJson, Dog.class);
            Cat deserializedCat = PolymorphicSerializationUtil.fromJsonWithGson(catJson, Cat.class);

            System.out.println("Deserialized dog name: " + deserializedDog.getName());
            System.out.println("Deserialized cat color: " + deserializedCat.getColor());

            // Fastjson序列化示例
            String dogJsonFast = PolymorphicSerializationUtil.toJsonWithFastjson(dog);
            String catJsonFast = PolymorphicSerializationUtil.toJsonWithFastjson(cat);

            System.out.println("Dog JSON (Fastjson): " + dogJsonFast);
            System.out.println("Cat JSON (Fastjson): " + catJsonFast);

            // Fastjson反序列化示例
            Dog deserializedDogFast = PolymorphicSerializationUtil.fromJsonWithFastjson(dogJsonFast, Dog.class);
            Cat deserializedCatFast = PolymorphicSerializationUtil.fromJsonWithFastjson(catJsonFast, Cat.class);

            System.out.println("Fastjson deserialized dog name: " + deserializedDogFast.getName());
            System.out.println("Fastjson deserialized cat color: " + deserializedCatFast.getColor());

        } catch (SerializationException e) {
            System.err.println("Serialization error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Gson 序列化和反序列化示例

序列化结果:

Dog JSON: {"type":"dog","name":"Buddy","age":3}
Cat JSON: {"type":"cat","name":"Whiskers","color":"gray"}

反序列化结果:

Deserialized dog name: Buddy
Deserialized cat color: gray

Fastjson 序列化和反序列化示例

序列化结果:

Dog JSON (Fastjson): {"@type":"com.example.serialization.Dog","name":"Buddy","age":3}
Cat JSON (Fastjson): {"@type":"com.example.serialization.Cat","name":"Whiskers","color":"gray"}

反序列化结果:

Fastjson deserialized dog name: Buddy
Fastjson deserialized cat color: gray
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏