【问题标题】:Cannot convert JSON HTTP Response to Java Object using Jackson无法使用 Jackson 将 JSON HTTP 响应转换为 Java 对象
【发布时间】:2016-02-21 13:46:56
【问题描述】:

我创建了一个 REST 服务,它发送 GET 请求以从指定的 URL 检索 JSON 响应。

尽管我的下一个问题是将 JSON 消息转换为 JAVA 对象,但我已经成功地检索到了 JSON 消息。

下面是我的 Rest 客户端:

public class RestADClient {


// HTTP GET request
public String sendGet(String url) throws Exception {

    URL obj = new URL(url);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();

    // optional default is GET
    con.setRequestMethod("GET");

    //add request header

    con.setRequestProperty("Authorization", "myAuthorizationProp");

    int responseCode = con.getResponseCode();
    System.out.println("\nSending 'GET' request to URL : " + url);
    System.out.println("Response Code : " + responseCode);

    BufferedReader in = new BufferedReader(
            new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();

    System.out.println("Response Message: " + response.toString());

    ObjectMapper mapper = new ObjectMapper();

    try {
        // Convert JSON string to Object
        String jsonInString = "[{  \"frequency\": \"ONE_MIN\",  \"metricId\": 2253538,  \"metricName\": \"DB|Server:1|IO|Data File Average Read Size\",  \"metricPath\": \"Databases|X|IO|Data File Average Read Size\",  \"metricValues\": [  {    \"count\": 14,    \"current\": 65323,    \"max\": 65536,    \"min\": 0,    \"occurrences\": 0,    \"standardDeviation\": 0,    \"startTimeInMillis\": 1447927800000,    \"sum\": 251408,    \"useRange\": true,    \"value\": 17958  }]}]";
        ADMetrics adMetrics = mapper.readValue(jsonInString, ADMetrics.class);
        System.out.println(adMetrics);

    } catch (JsonGenerationException e) {
        e.printStackTrace();
    } catch (JsonMappingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return response.toString();
}

}

下面是我的 ADMetrics POJO 类:

import java.util.List;
public class ADMetrics {

private String frequency;
private int metricId;
private String metricName;
private String metricPath;
private List<String> metricValues;
private int count;
private int current;
private int max;
private int min;
private int occurences;
private int standardDeviation;
private int startTimeInMillis;
private int sum;
private boolean useRange;
private int value;

public String getFrequency() {
    return frequency;
}

public void setFrequency(String frequency) {
    this.frequency = frequency;
}

public int getMetricId() {
    return metricId;
}

public void setMetricId(int metricId) {
    this.metricId = metricId;
}
public String getMetricName() {
    return metricName;
}

public void setMetricName(String metricName) {
    this.metricName = metricName;
}

public String getMetricPath() {
    return metricPath;
}

public void setMetricPath(String metricPath) {
    this.metricPath = metricPath;
}

public List<String> getMetricValues() {
    return metricValues;
}

public void setMetricValues(List<String> metricValues) {
    this.metricValues = metricValues;
}

public int getCount() {
    return count;
}

public void setCount(int count) {
    this.count = count;
}

public int getCurrent() {
    return current;
}

public void setCurrent(int current) {
    this.current = current;
}

public int getMax() {
    return max;
}

public void setMax(int max) {
    this.max = max;
}

public int getMin() {
    return min;
}

public void setMin(int min) {
    this.min = min;
}

public int getOccurences() {
    return occurences;
}

public void setOccurences(int occurences) {
    this.occurences = occurences;
}

public int getStandardDeviation() {
    return standardDeviation;
}

public void setStandardDeviation(int standardDeviation) {
    this.standardDeviation = standardDeviation;
}

public int getStartTimeInMillis() {
    return startTimeInMillis;
}

public void setStartTimeInMillis(int startTimeInMillis) {
    this.startTimeInMillis = startTimeInMillis;
}

public int getSum() {
    return sum;
}

public void setSum(int sum) {
    this.sum = sum;
}

public boolean isUseRange() {
    return useRange;
}

public void setUseRange(boolean useRange) {
    this.useRange = useRange;
}

public int getValue() {
    return value;
}

public void setValue(int value) {
    this.value = value;
}

下面是我的 JUnit 测试:

public class ADTest {

String url = "myURL";

@Test
public void testResponseContainsMetricFrequency() throws Exception {

    RestADClient restADClient = new RestADClient();


    assertTrue(restADClient.sendGet(url).contains("frequency"));
}}

当我运行测试时,我得到以下信息:

响应代码:200

响应消息:[{ "frequency": "ONE_MIN", "metricId": 2253538, "metricName": "DB|Server:169|IO|Data File Average Read Size", "metricPath": "Databases|QA -CARS|IO|数据文件平均读取大小", "metricValues": [ { "count": 13, "current": 66013, "max": 72003, "min": 0, "occurrences": 0, "standardDeviation ": 0, "startTimeInMillis": 1447929360000, "sum": 198688, "useRange": true, "value": 15284 }]}]

org.codehaus.jackson.map.JsonMappingException:无法从 START_ARRAY 令牌中反序列化 rest.client.ADMetrics 的实例 在 [来源:java.io.StringReader@78b729e6;行:1,列:1]

【问题讨论】:

标签: java json jackson gson appdynamics


【解决方案1】:

由于您收到的 JSON 有一个数组,因此您需要反序列化为一个对象列表。大概只是抓住列表中的第一个:

    List<ADMetrics> adMetricsList = mapper.readValue(jsonInString, new TypeReference<List<ADMetrics>>(){});
    ADMetrics adMetrics = adMetricsList.get(0);

或者,如果您不确定列表中还有什么,只想获取第一个元素,您可以分两步进行转换:

    JsonNode tree = mapper.readTree(jsonInString);
    ADMetrics adMetrics = mapper.convertValue(tree.get(0), ADMetrics.class);

【讨论】:

    【解决方案2】:

    你可以尝试在你的 pojo 类中实现序列化,如下所示

         public class ADMetrics implements Serializable{
    
    private static final long serialVersionUID = 1L;
    //All your variables and getter and setter method
    }
    

    方法一:

    另外你的 JSON 不是 JSONObject 它是一个 JSONARRAY,使用下面的代码将你上面的 String 转换为 JSONARRAY

    JsonArray jArray = new JsonParser().parse(json).getAsJsonArray();
    

    jArray 是来自 GSON 的 JSONArray,因此可以使用 GSON 来转换您需要的方式或将 GSON 转换为 JSON。

    方法二:

    直接转换上面输入的json
    Gson gson = new Gson();
                String output = gson.toJson(input);
                //System.out.println("output from gson "+output);
            JSONArray js = new JSONArray(output);
    

    然后像往常一样使用 json。

    【讨论】:

    • 在方法一中:使用这一行 JsonArray jArray = new JsonParser().parse(jsonInString).getAsJsonArray();
    【解决方案3】:

    从您的 JSON 中删除外部“[]”。您正在传递一个 ADMetrics 数组,而不是 readValue 反序列化程序所期望的单个 ADMetrics

    【讨论】:

      【解决方案4】:
      "[{  \"frequency\": \"ONE_MIN\",  \"metricId\": 2253538,  \"metricName\": \"DB|Server:1|IO|Data File Average Read Size\",  \"metricPath\": \"Databases|X|IO|Data File Average Read Size\",  \"metricValues\": [  {    \"count\": 14,    \"current\": 65323,    \"max\": 65536,    \"min\": 0,    \"occurrences\": 0,    \"standardDeviation\": 0,    \"startTimeInMillis\": 1447927800000,    \"sum\": 251408,    \"useRange\": true,    \"value\": 17958  }]}]"
      

      JSON 对象的格式不正确。

      试试这个:

      "{  \"frequency\": \"ONE_MIN\",  \"metricId\": 2253538,  \"metricName\": \"DB|Server:1|IO|Data File Average Read Size\",  \"metricPath\": \"Databases|X|IO|Data File Average Read Size\",  \"metricValues\": [  {    \"count\": 14,    \"current\": 65323,    \"max\": 65536,    \"min\": 0,    \"occurrences\": 0,    \"standardDeviation\": 0,    \"startTimeInMillis\": 1447927800000,    \"sum\": 251408,    \"useRange\": true,    \"value\": 17958  }]}"
      

      【讨论】:

        猜你喜欢
        • 2013-03-25
        • 1970-01-01
        • 2016-08-05
        • 1970-01-01
        • 2018-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多