【问题标题】:Parse Json to object containing objects将 Json 解析为包含对象的对象
【发布时间】:2019-12-07 00:52:38
【问题描述】:

我从 accuweather 获得以下带有 json 的代码

{  
 "Headline":{  
      "EffectiveDate":"2019-07-29T07:00:00+06:00",
      "EffectiveEpochDate":1564362000,
      "Severity":3,
      "Text":"The heat wave will continue through Friday",
      "Category":"heat",
      "EndDate":"2019-08-02T19:00:00+06:00",
      "EndEpochDate":1564750800
   },
   "DailyForecasts":[  
      {  
         "Date":"2019-07-29T07:00:00+06:00",
         "EpochDate":1564362000,
         "Temperature":{  
            "Minimum":{  
               "Value":19.1,
               "Unit":"C",
               "UnitType":17
            },
            "Maximum":{  
               "Value":36.7,
               "Unit":"C",
               "UnitType":17
            }
         },
         "Day":{  
            "Icon":30,
            "IconPhrase":"Hot",
            "HasPrecipitation":false
         },
         "Night":{  
            "Icon":35,
            "IconPhrase":"Partly cloudy",
            "HasPrecipitation":false
         },
         "Sources":[  
            "AccuWeather"
         ]
      }
   ]
}

我尝试通过jackson将此对象解析为POJO

public static void main( String[] args )
{
    String x = "{\"Headline\":{\"EffectiveDate\":\"2019-07-29T07:00:00+06:00\",\"EffectiveEpochDate\":1564362000,\"Severity\":3,\"Text\":\"The heat wave will continue through Friday\",\"Category\":\"heat\",\"EndDate\":\"2019-08-02T19:00:00+06:00\",\"EndEpochDate\":1564750800},\"DailyForecasts\":[{\"Date\":\"2019-07-29T07:00:00+06:00\",\"EpochDate\":1564362000,\"Temperature\":{\"Minimum\":{\"Value\":19.1,\"Unit\":\"C\",\"UnitType\":17},\"Maximum\":{\"Value\":36.7,\"Unit\":\"C\",\"UnitType\":17}},\"Day\":{\"Icon\":30,\"IconPhrase\":\"Hot\",\"HasPrecipitation\":false},\"Night\":{\"Icon\":35,\"IconPhrase\":\"Partly cloudy\",\"HasPrecipitation\":false},\"Sources\":[\"AccuWeather\"]}]}";
    ObjectMapper objectMapper = new ObjectMapper();

    try {
        Weather weather = objectMapper.readValue(x, Weather.class);

        System.out.println(weather);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我在 json 中指定了所有模型,例如 HeadlineDailyForecasts 的数组、Temperature 组成的 TemperatureItems(在 json 中命名为最小值和最大值)等等,它们都有私有字段以及公共构造函数、getter 和 setter。但是我没有一些字段,因为我想省略它们(白天、夜晚、EpochDate、Source)。

当我运行程序时出现错误

com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造test.models.weather.Weather 的实例(没有像默认构造一样的创建者):无法从对象值反序列化(没有基于委托或基于属性的创建者)

我也尝试过Gson,但它返回的对象为 Null 值

我做错了吗?还有其他方法吗?

编辑:这些是模型,@LazerBass 是对的,因为我一开始没有包含默认构造函数,现在错误已经改变:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:无法识别的字段“Headline”(类 test.models.weather.Weather),未标记为可忽略(2 个已知属性:“headline”、“dailyForecasts”])

public class TemperatureItem {
    public double value;
    public String unit;
    public String unitType;

    public TemperatureItem() {

    }

    //Getters and setters
}


public class Temperature {
    private TemperatureItem maximum;
    private TemperatureItem minimum;

    public Temperature(TemperatureItem maximum, TemperatureItem minimum) {
        this.maximum = maximum;
        this.minimum = minimum;
    }

    public Temperature() {

    }
    //Getters and setters
}

public class DailyForecasts {
    private LocalDateTime date;
    private Temperature temperature;

    public DailyForecasts(LocalDateTime date, Temperature temperature) {
        this.date = date;
        this.temperature = temperature;
    }

    public DailyForecasts() {

    }
    //Getters and setters
}

public class Headline {
    private LocalDateTime effectiveDate;
    private int severity;
    private String text;
    private String category;
    private LocalDateTime endDate;

    public Headline() {

    }

    public Headline(LocalDateTime effectiveDate, Integer severity, String text, String category, LocalDateTime endDate) {
        this.effectiveDate = effectiveDate;
        this.severity = severity;
        this.text = text;
        this.category = category;
        this.endDate = endDate;
    }
    //Getters and setters
}

public class Weather {
        private Headline headline;
        private DailyForecasts[] dailyForecasts;

        public Weather() {

        }
        public Weather(Headline headline, DailyForecasts[] dailyForecasts) {
            this.headline = headline;
            this.dailyForecasts = dailyForecasts;
        }
        //Getters and setters
}

我发现,如果我将 json 字符串转换为小写,我可以获得一些值,尽管 ArrayLocalDateTime 没有被解析

【问题讨论】:

  • 没有看到 Weather 定义,但尝试 Weather weath = (Weather.class)JSON.deserializeStrict(x,Weather.class);
  • 添加你定义的模型会更好。
  • 您可以对模型使用 JsonIgnore 或 JsonIgnoreProperties,这样您就可以忽略那些不需要的字段。
  • 您的Weather 课程不正确。如果您需要帮助修复它,请编辑问题并向我们展示它的源代码及其嵌入式类(HeadlineDailyForecastTemperature、...)
  • 好的,现在已经更新了问题,谢谢@MadhuBhat

标签: java json jackson


【解决方案1】:

要生成 Weather 类及其对应的类,请使用以下链接并将源类型选择为 json。它将根据 json 字符串生成所需的类。

http://www.jsonschema2pojo.org/

生成类后,您可以使用@JsonIgnore 注释不需要的字段。

【讨论】:

  • 谢谢,使用生成的类正确反序列化
【解决方案2】:

Jackson 失败并显示类似“没有创建者,如默认构造,存在”这样的消息时,它需要默认构造函数,public no-argument 构造函数为您在模型中拥有的每个 POJO 类.

当它失败并显示“无法识别的字段...未标记为可忽略...”之类的消息时,您需要禁用FAIL_ON_UNKNOWN_PROPERTIES 功能。

另见:

  1. Jackson Unmarshalling JSON with Unknown Properties
  2. jackson delay deserializing field

【讨论】:

    【解决方案3】:

    从异常消息来看,我猜您的 Weather 类缺少无参数构造函数。尝试添加一个。例如

    public class Weather {
        public Weather() {
            // no arg constructor needed for jackson
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-26
      相关资源
      最近更新 更多