【问题标题】:Deserializing Enum, which contains Map反序列化 Enum,其中包含 Map
【发布时间】:2019-11-20 13:33:46
【问题描述】:

我的枚举:

@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 得到的邮递员响应:

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

}

标题几乎概括了我的需要。任何想法如何在我的代码中序列化邮递员响应,因此我有枚举,其中包含所有属性,包括“费率”映射?

提前致谢。

【问题讨论】:

    标签: java rest enums jackson deserialization


    【解决方案1】:

    您需要创建一个带有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,而是每次都创建新的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-25
      • 1970-01-01
      • 1970-01-01
      • 2018-03-20
      • 1970-01-01
      • 1970-01-01
      • 2020-11-14
      • 2012-06-14
      相关资源
      最近更新 更多