java - 反序列化 Enum,其中包含 Map

标签 java rest enums jackson deserialization

我的枚举:

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Currency {

    USD("USD", "United States Dollar"),
    EUR("EUR", "Euro"),
    BGP("BGP", "British Pound"),
    AUD("AUD", "Australian Dollar"),
    CAD("CAD", "Canadian Dollar");

    private final String shortName;
    private final String fullName;
    private Map<Enum, Double> rates;

    Currency(String shortName, String fullName) {
        this.shortName = shortName;
        this.fullName = fullName;
        this.rates = new HashMap<>();
    }

    public String getShortName() {
        return shortName;
    }

    public String getFullName() {
        return fullName;
    }

    public Map<Enum, Double> getRates() {
        return rates;
    }

}

我从另一个rest api得到的 postman 响应:

{
"shortName": "EUR",
"fullName": "Euro",
"rates": {
    "AUD": 1.62,
    "CAD": 1.47,
    "USD": 1.11,
    "BGP": 0.86,
    "EUR": 1.0
}

}

标题几乎概括了我的需要。有什么想法如何在我的代码中序列化 postman 响应,以便我得到枚举作为结果,其中包含所有属性,包括“费率” map ?

提前致谢。

最佳答案

您需要创建一个使用 com.fasterxml.jackson.annotation.JsonCreator 注释进行注释的 static 工厂方法。如果整个 JSON Object 表示 enumJackson 会自动将其转换为 Map,因此该方法应该有签名如下所示:

@JsonCreator
public static Currency from(Map<String, Object> value)

下面的展示提供了完整的实现:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./src/main/resources/test.json");

        ObjectMapper mapper = new ObjectMapper();

        Currency currency = mapper.readValue(jsonFile, Currency.class);
        System.out.println(currency + " => " + currency.getRates());
    }
}

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
enum Currency {

    USD("USD", "United States Dollar"),
    EUR("EUR", "Euro"),
    BGP("BGP", "British Pound"),
    AUD("AUD", "Australian Dollar"),
    CAD("CAD", "Canadian Dollar");

    private final String shortName;
    private final String fullName;
    private Map<Enum, Double> rates;

    Currency(String shortName, String fullName) {
        this.shortName = shortName;
        this.fullName = fullName;
        this.rates = Collections.emptyMap();
    }

    public String getShortName() {
        return shortName;
    }

    public String getFullName() {
        return fullName;
    }

    public Map<Enum, Double> getRates() {
        return rates;
    }

    public static Currency fromShortName(String value) {
        for (Currency currency : values()) {
            if (currency.getShortName().equals(value)) {
                return currency;
            }
        }

        throw new IllegalArgumentException(value + " is not found!");
    }

    @JsonCreator
    public static Currency from(Map<String, Object> value) {
        String shortName = value.getOrDefault("shortName", "").toString();
        Currency currency = fromShortName(shortName);

        Map<String, Double> rates = (Map<String, Double>) value.getOrDefault("rates", Collections.emptyMap());
        Map<Enum, Double> newRates = new HashMap<>(9);
        rates.forEach((k, v) -> {
            newRates.put(Currency.fromShortName(k), v);
        });

        currency.rates = Collections.unmodifiableMap(newRates);
        return currency;
    }
}

上面的代码打印:

EUR => {EUR=1.0, AUD=1.62, CAD=1.47, USD=1.11, BGP=0.86}

警告

enum 应该是 Immutable object将费率 Map 保留在内部并不是一个好主意。您绝对应该尝试将其从 enum 中删除。在多线程环境中,你需要保证这个Map在读取过程中不会改变。因此,在实现中我不会更改已使用的 Map 而是每次都会创建新的。

关于java - 反序列化 Enum,其中包含 Map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58955630/

相关文章:

javascript - 在 CloudCode 私有(private)函数中使用 Parse 对象

java - Java 7 中是否有 ImmutableEnumSet 的计划?

java - 在 JFace 对话框的中心添加确定按钮

c# - 如何将 IList<MyObject> 作为参数传递给 Web API 中的 POST 方法?

用于curl请求的Java代码

rest - 如何在 C# 中构建部分项目 RESTful API?

c# - 是否可以创建通用的按位枚举 'IsOptionSet()' 方法?

java - Java 5.0 之后如何比较枚举类型?

java - JsonDeserializer 不处理空值

java - 为 ProgressBar Java 添加容器监听器