RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1437648
Accepted
Roman
Roman
Asked:2022-08-09 15:14:27 +0000 UTC2022-08-09 15:14:27 +0000 UTC 2022-08-09 15:14:27 +0000 UTC

Jackson 如何解析没有名称的数组

  • 772

我正在尝试从天气 apishka 获得响应 apishka 向城市坐标请求发送这样的响应

[
    {
        "name": "Moscow",
        "local_names": {
            "it": "Mosca",
            "zh": "莫斯科",
            "lv": "Maskava",
            "id": "Moskwa",
            "ay": "Mosku",
            "lt": "Maskva",
            "ascii": "Moscow",
            "sh": "Moskva",
            "uz": "Moskva",
            "st": "Moscow",
            "co": "Moscù",
            "bo": "མོ་སི་ཁོ།",
            "fi": "Moskova",
            "wo": "Mosku",
            "dz": "མོསི་ཀོ",
            "sl": "Moskva",
            "ps": "مسکو",
            "sc": "Mosca",
            "hr": "Moskva",
            "kv": "Мӧскуа",
            "tk": "Moskwa",
            "sr": "Москва",
            "mg": "Moskva",
            "ko": "모스크바",
            "wa": "Moscou",
            "sg": "Moscow",
            "sv": "Moskva",
            "ch": "Moscow",
            "mn": "Москва",
            "ta": "மாஸ்கோ",
            "am": "ሞስኮ",
            "an": "Moscú",
            "io": "Moskva",
            "su": "Moskwa",
            "ro": "Moscova",
            "oc": "Moscòu",
            "feature_name": "Moscow",
            "bg": "Москва",
            "nn": "Moskva",
            "en": "Moscow",
            "li": "Moskou",
            "ga": "Moscó",
            "ak": "Moscow",
            "ba": "Мәскәү",
            "da": "Moskva",
            "so": "Moskow",
            "ru": "Москва",
            "be": "Масква",
            "is": "Moskva",
            "eo": "Moskvo",
            "cu": "Москъва",
            "uk": "Москва",
            "cs": "Moskva",
            "sk": "Moskva",
            "vo": "Moskva",
            "ab": "Москва",
            "qu": "Moskwa",
            "kg": "Moskva",
            "cy": "Moscfa",
            "az": "Moskva",
            "pl": "Moskwa",
            "jv": "Moskwa",
            "fo": "Moskva",
            "ia": "Moscova",
            "lg": "Moosko",
            "hu": "Moszkva",
            "vi": "Mát-xcơ-va",
            "eu": "Mosku",
            "mt": "Moska",
            "nb": "Moskva",
            "pt": "Moscou",
            "tl": "Moscow",
            "ar": "موسكو",
            "he": "מוסקווה",
            "gv": "Moscow",
            "sw": "Moscow",
            "de": "Moskau",
            "gd": "Moscobha",
            "ja": "モスクワ",
            "yo": "Mọsko",
            "dv": "މޮސްކޯ",
            "cv": "Мускав",
            "bi": "Moskow",
            "fa": "مسکو",
            "gn": "Mosku",
            "no": "Moskva",
            "iu": "ᒨᔅᑯ",
            "na": "Moscow",
            "bs": "Moskva",
            "kk": "Мәскеу",
            "ml": "മോസ്കോ",
            "zu": "IMoskwa",
            "za": "Moscow",
            "ca": "Moscou",
            "hi": "मास्को",
            "ln": "Moskú",
            "la": "Moscua",
            "mi": "Mohikau",
            "av": "Москва",
            "gl": "Moscova - Москва",
            "es": "Moscú",
            "os": "Мæскуы",
            "af": "Moskou",
            "se": "Moskva",
            "ht": "Moskou",
            "nl": "Moskou",
            "kn": "ಮಾಸ್ಕೋ",
            "yi": "מאסקווע",
            "ty": "Moscou",
            "br": "Moskov",
            "el": "Μόσχα",
            "ce": "Москох",
            "tt": "Мәскәү",
            "tr": "Moskova",
            "ku": "Moskow",
            "te": "మాస్కో",
            "ie": "Moskwa",
            "sq": "Moska",
            "et": "Moskva",
            "ss": "Moscow",
            "hy": "Մոսկվա",
            "tg": "Маскав",
            "kl": "Moskva",
            "kw": "Moskva",
            "mr": "मॉस्को",
            "ka": "მოსკოვი",
            "ky": "Москва",
            "fr": "Moscou",
            "my": "မော်စကိုမြို့",
            "sm": "Moscow",
            "fy": "Moskou",
            "mk": "Москва",
            "ms": "Moscow",
            "th": "มอสโก",
            "ug": "Moskwa",
            "ur": "ماسکو",
            "bn": "মস্কো"
        },
        "lat": 55.7504461,
        "lon": 37.6174943,
        "country": "RU",
        "state": "Moscow"
    }
]

但作为回应,我得到了这样的例外

Exception in thread "main" org.springframework.web.client.RestClientException: Error while extracting response for type [class com.romanperkov.spring.rest.entity.cord] and content type [application/json;charset=utf-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `com.romanperkov.spring.rest.entity.cord` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.romanperkov.spring.rest.entity.cord` out of START_ARRAY token
 at [Source: (PushbackInputStream); line: 1, column: 1]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:120)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:741)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:315)
    at com.romanperkov.spring.rest.Communication.test(Communication.java:81)
    at com.romanperkov.spring.rest.App.main(App.java:35)
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `com.romanperkov.spring.rest.entity.cord` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.romanperkov.spring.rest.entity.cord` out of START_ARRAY token
 at [Source: (PushbackInputStream); line: 1, column: 1]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:284)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:242)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:105)
    ... 5 more
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.romanperkov.spring.rest.entity.cord` out of START_ARRAY token
 at [Source: (PushbackInputStream); line: 1, column: 1]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1468)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1242)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1190)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeFromArray(BeanDeserializer.java:604)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:190)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:166)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3521)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:273)
    ... 7 more

Process finished with exit code 1

我了解问题是apishka的响应以方括号开头,即它返回一个数组,但它没有名称,这种情况下如何进行?

描述要从响应 API 获取的实体的类

@Getter
@Setter
@NoArgsConstructor
public class cord {

    private List<String> name;
}

问题的解决方法是将类指定为数组

String url="http://api.openweathermap.org/geo/1.0/direct?q=QWERTY&limit=5&appid=fe7e6bcec3fedc63d4a158abd1c3c3eb";
        cord[] responseEntity=restTemplate.getForObject
                (url.replace("QWERTY","москва"), cord[].class);
        System.out.println(responseEntity[0]);
java json
  • 2 2 个回答
  • 46 Views

2 个回答

  • Voted
  1. Best Answer
    Михаил Ребров
    2022-08-09T16:10:08Z2022-08-09T16:10:08Z

    模型

    描述我们要提取的对象

    本地化的城市名称更容易融入Map<String, String>

    private Map<String, String> localNames;
    

    为了不违反约定并按应有的方式调用变量 CamelCase,而不是 JSON 中的 snake_case,我们将使用 JSON 中的字段名称在字段上添加注释

    @JsonProperty("local_names")
    private Map<String, String> localNames;
    

    为了更方便地使用 Map 中的本地化名称,您可以添加一个辅助方法,通过区域设置代码提取所需的名称

    public String getLocalName(String locale){
        return localNames.get(locale);
    }
    

    因此,要获得法语名称,您需要调用:

    city.getLocalName("fr")
    

    全班:

    import com.fasterxml.jackson.annotation.JsonProperty;
    import java.util.HashMap;
    import java.util.Map;
    
    public class City {
        private String name;
        @JsonProperty("local_names")
        private Map<String, String> localNames;
        private Double lat;
        private Double lon;
        private String country;
        private String state;
    
        public City() {
            this.localNames = new HashMap<>();
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Map<String, String> getLocalNames() {
            return localNames;
        }
    
        public void setLocalNames(Map<String, String> localNames) {
            this.localNames = localNames;
        }
    
        public Double getLat() {
            return lat;
        }
    
        public void setLat(Double lat) {
            this.lat = lat;
        }
    
        public Double getLon() {
            return lon;
        }
    
        public void setLon(Double lon) {
            this.lon = lon;
        }
    
        public String getCountry() {
            return country;
        }
    
        public void setCountry(String country) {
            this.country = country;
        }
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
    
        public String getLocalName(String locale){
            return localNames.get(locale);
        }
    }
    
    

    萃取

    从 JSON 中提取对象最不愉快的时刻是参数化类型(它们是泛型)

    在我们的例子中,对象列表直接返回给我们,我们必须以某种方式确定类型。

    我们List.class无法指定。

    对于此类任务,Jackson 有一个类型工厂,可以帮助您创建基于集合类和嵌套对象类的泛型类型描述

    JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, City.class);
    

    从 json 中提取对象的实际代码

    String json = getSOJsonString(); // получаем JSON
    ObjectMapper mapper = new ObjectMapper();
    // Так как дженерики нельзя просто указать через `getClass` 
    // Создаем тип для извлечения коллекции объектов 
    // с помощью встроенных в Jackson конструкторов типов
    JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, City.class);
    // маппим одно на другое
    List<City> cities = mapper.readValue(json, type);
    for (City city: cities) {
        // System.out.println(city.getName());
        // тут выводим все что нам надо
    }
    

    一切都正确检索。
    这是从调试器中提取的示例: 在此处输入图像描述

    更新

    На момент начала написания ответа кода с RestTemplate в вопросе не было, поэтому дополняю вариант с онным.

    Конкретно в случае с RestTemplate тип лучше указывать с помощью вспомогательного класса Spring'а, предназначенного ровно для того же что и вышеописанная фабрика.

    В Spring есть класс ParameterizedTypeReference с помощью которого можно описать тип параметризируемого объекта (или дженерика)

    Делается это так:

    ParameterizedTypeReference<List<City>> type = new ParameterizedTypeReference<List<City>>() {};
    

    при этом данный тип можно пристроить далеко не в каждый метод RestTemplate.

    Лучше всего воспользоваться следующим способом:

    restTemplate.exchange(myUrl, HttpMethod.GET, null, type);
    

    В итоге код получения и извлечения объектов из REST'сервиса будет выглядеть так:

    String url="http://api.openweathermap.org/geo/1.0/direct?q=QWERTY&limit=5&appid=fe7e6bcec3fedc63d4a158abd1c3c3eb";
    ParameterizedTypeReference<List<City>> type = new ParameterizedTypeReference<List<City>>() {};
    List<City> cities = restTemplate.exchange(url.replace("QWERTY","москва"), HttpMethod.GET, null, type).getBody();
    
    for (City city: cities) {
        System.out.println(city);
    }
    

    注意:
    在你的情况下,只会有一个类City,而不是一个类coord
    。我没有举手那样称呼类,所以我从我提到的类似答案中取了名字。
    类必须以大写字母命名。
    这是一个约定。

    不知怎的,我猜...

    String url="http://api.openweathermap.org/geo/1.0/direct?q=QWERTY&limit=5&appid=fe7e6bcec3fedc63d4a158abd1c3c3eb";
    ParameterizedTypeReference<List<coord>> type = new ParameterizedTypeReference<List<coord>>() {};
    List<coord> coords = restTemplate.exchange(url.replace("QWERTY","москва"), HttpMethod.GET, null, type).getBody();
    
    for (coord c: coords) {
        System.out.println(c);
    }
    
    • 1
  2. Vadik
    2022-08-09T16:27:56Z2022-08-09T16:27:56Z

    你想解析一个对象,你会得到一个列表。传递TypeReferencecList<City>来解析列表:

    ObjectMapper objectMapper = new ObjectMapper();
    String content = "[{\"name\": \"Moscow\"}]";
    TypeReference<List<City>> type = new TypeReference<>() {};
    List<City> cities = objectMapper.readValue(content, type);
    System.out.println(cities);
    
    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5