【问题标题】:JsonMappingException while parse an enumeration解析枚举时出现 JsonMappingException
【发布时间】:2018-05-23 13:03:28
【问题描述】:

我有一个带有标记为@JsonCreator 的构造函数的类,用于将我的JSON 字符串反序列化到我的类Meal

public class Meal {
    private int proteins;
    private int lipids;
    private int carbohydrates;
    private int totalKcal;
    private List<Dish> dishes;
    private int slot;
    private MealEnum mealType;

    @JsonCreator
    public Meal(@JsonProperty("mealType") MealEnum mealType, @JsonProperty("dishes") List<Dish> dishes,
                @JsonProperty("slot") int slot, @JsonProperty("totalKcal") int totalKcal,
                @JsonProperty("carbohydrates") int carbohydrates, @JsonProperty("proteins") int proteins,
                @JsonProperty("lipids") int lipids) {
        this.mealType = mealType;
        this.dishes = dishes;
        this.slot = slot;
        this.totalKcal = totalKcal;
        this.carbohydrates = carbohydrates;
        this.proteins = proteins;
        this.lipids = lipids;
    }

我也有这个带有 @JsonCreator 标记的构造函数的枚举:

public enum MealEnum {
    BREAKFAST(0, "BREAKFAST"),
    LUNCH(1, "LUNCH"),
    SUPPER(2, "SUPPER");
    @JsonIgnore
    private final int intValue;
    private final String stringValue;

    MealEnum(int intValue, String stringValue) {
        this.intValue = intValue;
        this.stringValue = Objects.requireNonNull(stringValue);
    }

    @JsonCreator
    MealEnum(@JsonProperty("mealType") String stringValue) {
        this.intValue = DynamicDietistUtils.getMealEnumFromMealType(stringValue);
        this.stringValue = stringValue;
    }

    public int getIntValue() {
        return this.intValue;
    }

    public String getStringValue() {
        return this.stringValue;
    }
}

要反序列化的 JSON 如下:

{
    "mealType": "BREAKFAST",
    "proteins": 60,
    "lipids": 147,
    "carbohydrates": 461,
    "totalKcal": 664,
    "dishes": [{
        "id": 0,
        "description": "burro (10g)",
        "proteins": 0.0,
        "lipids": 72.0,
        "carbohydrates": 0.0,
        "kcal": 76
    }, {
        "id": 0,
        "description": "pane comune (100g)",
        "proteins": 32.0,
        "lipids": 0.0,
        "carbohydrates": 252.0,
        "kcal": 290
    }],
    "slot": 1
}

Jackson 尝试反序列化 JSON 时,出现以下错误:

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of mainpackage.data.model.Meal: no String-argument constructor/factory method to deserialize from String value ('mealType')

我哪里做错了? 提前致谢。

【问题讨论】:

    标签: java json spring jackson


    【解决方案1】:

    我认为问题在于,在 java 中,除了枚举值初始化列表之外,您无法从任何地方调用枚举构造函数。
    所以杰克逊不能使用枚举构造函数,你可以创建静态方法来代替你从字符串中查找值。

    @JsonCreator
    public static MealEnum forValue(String value) {
        return MaelEnum.valueOf(value); //or any other way to lookup your enum value for given string
    }
    

    【讨论】:

    • @parion 您是否从构造函数中删除了注释?错误是一样的吗?
    • 是的,是一样的。
    • @pairon 你用的是哪个杰克逊版本?还要确保您的创建者方法是公共静态的(不确定,也许您也可以使用 package-local/protected)。
    • 杰克逊 2.* 是版本
    【解决方案2】:

    将您的枚举 json 创建者更改为工厂方法

    @JsonCreator
    public static MealEnum fromString(String stringValue) {
        int value = DynamicDietistUtils.getMealEnumFromMealType(stringValue);
        for(MealEnum e : values()) {
            if(value == e.getIntValue()) {
                return e;
            }  
        }
        throw new IllegalArgumentException(stringValue);
    
    }
    

    或(如果 json 中的 mealType 与 Enum 常量匹配)

    @JsonCreator
    public static MealEnum fromString(String stringValue) {
    
         // for case insensitive use stringValue.toUpperCase()
         return MealEnum.valueOf(stringValue);
    }
    

    【讨论】:

    • 是的,mealType 与枚举常量匹配,但工厂方法无法解决错误。
    • 它应该可以工作,检查你的项目没有杰克逊 1 和 2。
    • 我还用@JsonProperty("mealType") 标记了“String stringValue”。这是一个错误吗?
    • JsonProperty / @JsonIgnore 在枚举中没有意义
    • @JsonCreator 方法应该是public static
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-25
    • 2021-07-15
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 2015-08-12
    • 2012-04-03
    相关资源
    最近更新 更多