【问题标题】:Read/Parse JSON with Java使用 Java 读取/解析 JSON
【发布时间】:2012-02-07 22:15:30
【问题描述】:

我从以下 YAHOO url 获得了一个 JSON 对象,它将使用查询返回一个股票代码。网址是。

    http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=Siemens&callback=YAHOO.Finance.SymbolSuggest.ssCallback

当我使用在线 json 验证器时,YAHOO 返回的 JSON 对象似乎不是 100% 有效的。

网站

http://jsonformatter.curiousconcept.com/

告诉我,JSON 对象无效。所以我决定使用 YAHOO 网络服务的子字符串,它是一个有效的 JSON 对象。在这种情况下,我使用的是输出

{"ResultSet":{"Query":"siemens","Result":[{"symbol":"SI", ... }]}}

有了这个子字符串,我的所有验证器都告诉我,我这里有一个有效的 JSON 对象。

我的 Java 代码,我试图反序列化我的 JSON 对象,如下所示:

import java.util.List;

public class ResultSet {
private String query;
private List<Result> result;

public String getQuery() {
    return this.query;
}

public void setQuery(String query) {
    this.query = query;
}

public List<Result> getResult() {
    return this.result;
}

public void setResult(List<Result> result) {
    this.result = result;
}
}

public class Result {
private String exch;
private String exchDisp;
private String name;
private String symbol;
private String type;
private String typeDisp;

public String getExch() {
    return this.exch;
}

public void setExch(String exch) {
    this.exch = exch;
}

public String getExchDisp() {
    return this.exchDisp;
}

public void setExchDisp(String exchDisp) {
    this.exchDisp = exchDisp;
}

public String getName() {
    return this.name;
}

public void setName(String name) {
    this.name = name;
}

public String getSymbol() {
    return this.symbol;
}

public void setSymbol(String symbol) {
    this.symbol = symbol;
}

public String getType() {
    return this.type;
}

public void setType(String type) {
    this.type = type;
}

public String getTypeDisp() {
    return this.typeDisp;
}

public void setTypeDisp(String typeDisp) {
    this.typeDisp = typeDisp;
}
}

我尝试使用 Google 的 GSON 反序列化对象的代码如下所示。

public String getTickerSymbol() {
    String content = new URLContentLoader(url).getContent();
    content = content.substring(43, content.length()-1);

    ResultSet data = new Gson().fromJson(content, ResultSet.class);

    System.out.println(">>" + data.getResult());

    return null;
}

名为“content”的变量的内容是

{"ResultSet":{"Query":"siemens","Result":[{"symbol":"SI","name": "Siemens AG","exch": "NYQ","type": "S","exchDisp":"NYSE","typeDisp":"Equity"},{"symbol":"SIE.DE","name": "Siemens AG","exch": "GER","type": "S","exchDisp":"XETRA","typeDisp":"Equity"},{"symbol":"SIE.MU","name": "SIEMENS N","exch": "MUN","type": "S","exchDisp":"Munich","typeDisp":"Equity"},{"symbol":"SIEMENS.NS","name": "Siemens Ltd.","exch": "NSI","type": "S","exchDisp":"NSE","typeDisp":"Equity"},{"symbol":"SIE.MI","name": "Siemens AG","exch": "MIL","type": "S","exchDisp":"Milan","typeDisp":"Equity"},{"symbol":"SIE.F","name": "SIEMENS N","exch": "FRA","type": "S","exchDisp":"Frankfurt","typeDisp":"Equity"},{"symbol":"SIEMENS.BO","name": "Siemens Ltd.","exch": "BSE","type": "S","exchDisp":"Bombay","typeDisp":"Equity"},{"symbol":"SIEB.SG","name": "SIEMENS SP.ADR","exch": "STU","type": "S","exchDisp":"Stuttgart","typeDisp":"Equity"},{"symbol":"SIEB.DE","name": "Siemens AG","exch": "GER","type": "S","exchDisp":"XETRA","typeDisp":"Equity"},{"symbol":"SIE.L","name": "Siemens AG","exch": "LSE","type": "S","exchDisp":"London","typeDisp":"Equity"}]}}

函数调用 data.getResult() 返回值“null”。函数 getTickerSymbol 的输出打印出以下控制台输出。

>>null

有人知道为什么对象没有以正确的方式反序列化吗?

我的目标是使用 YAHOO 网络服务来检索公司的股票代码以接收其股票报价。

解决方案

主要问题是大写。 Q uery 是用大写的 Q 编写的。在类 ResultSet 中它是用 q 编写的。数据绑定机制无法开箱即用地处理这个问题。使用 jackson,您可以使用 Annotations,这样您就不必修改 JSON-Object 和原始变量名称。在 Java 中,使用大写的变量名并不是一种常见的代码风格。使用 Jackson Annotions,您可以手动进行映射。有效!

通过下面的代码,我让它工作了。感谢您的建议:-)

杰克逊库的解决方案

import java.util.List;
import org.codehaus.jackson.annotate.JsonProperty;

public class ResultSet {
private String query;
private List<Result> result;

public String getQuery() {
    return this.query;
}

@JsonProperty("Query")
public void setQuery(String query) {
    this.query = query;
}

public List<Result> getResult() {
    return this.result;
}

@JsonProperty("Result")
public void setResult(List<Result> result) {
    this.result = result;
}
}

Helper 类的代码

import org.codehaus.jackson.map.ObjectMapper;

public class JsonUtils {
public static <T> T parseJson(String json, Class<T> resultType) {
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        return objectMapper.readValue(json, resultType);
    } catch (Exception e) {
        System.err.println(e.getMessage());
    }
    return null;
}
}

构建对象

ResultSet rs = JsonUtils.parseJson(content, ResultSet.class);

for ( Result result : rs.getResult() ) {
    System.out.println(result.getSymbol());
}

【问题讨论】:

    标签: java json parsing gson


    【解决方案1】:

    发生这种情况是因为 ResultSet.class 并不真正对应于给定的 JSON。不幸的是,您需要另一个类作为 ResultSet 的容器:

    public class JsonContainer {
    
      private ResultSet jsonContainer;
    
      // getter/setter
    }
    

    那么你需要这样做:

    JsonContainer data = new Gson().fromJson(content, JsonContainer.class);
    

    如果这不起作用,那么您必须使用骆驼案:将private ResultSet jsonContainer; 更改为private ResultSet JsonContainer; 或使用@SerializedName。

    【讨论】:

    • 我在另一个 stackoverflow 线程中读到了这个提示。不幸的是,这对我没有帮助:-/还有其他建议吗?
    • 是大小写问题。
    【解决方案2】:

    问题在于 ResultSet 类中没有名为 ResultSet 的属性。你应该反序列化这个子字符串:

    {"Query":"siemens","Result":[{"symbol":"SI","name": "Siemens AG","exch": "NYQ","type": "S","exchDisp":"NYSE","typeDisp":"Equity"},{"symbol":"SIE.DE","name": "Siemens AG","exch": "GER","type": "S","exchDisp":"XETRA","typeDisp":"Equity"},{"symbol":"SIE.MU","name": "SIEMENS N","exch": "MUN","type": "S","exchDisp":"Munich","typeDisp":"Equity"},{"symbol":"SIEMENS.NS","name": "Siemens Ltd.","exch": "NSI","type": "S","exchDisp":"NSE","typeDisp":"Equity"},{"symbol":"SIE.MI","name": "Siemens AG","exch": "MIL","type": "S","exchDisp":"Milan","typeDisp":"Equity"},{"symbol":"SIE.F","name": "SIEMENS N","exch": "FRA","type": "S","exchDisp":"Frankfurt","typeDisp":"Equity"},{"symbol":"SIEMENS.BO","name": "Siemens Ltd.","exch": "BSE","type": "S","exchDisp":"Bombay","typeDisp":"Equity"},{"symbol":"SIEB.SG","name": "SIEMENS SP.ADR","exch": "STU","type": "S","exchDisp":"Stuttgart","typeDisp":"Equity"},{"symbol":"SIEB.DE","name": "Siemens AG","exch": "GER","type": "S","exchDisp":"XETRA","typeDisp":"Equity"},{"symbol":"SIE.L","name": "Siemens AG","exch": "LSE","type": "S","exchDisp":"London","typeDisp":"Equity"}]}
    

    【讨论】:

    • 我不明白。有两个类 ResultSet.class 和 Result.class - 我已经使用jsongen.byingtondesign.com 生成了这些类,无论如何,我也尝试过你的建议,只解析结果数组。为此,我像您的示例中一样缩短了 JSON 对象。仍然没有运气。当我想使用我的 get 方法检索值时,我总是得到“null”。调试器也没有帮助我:-/
    • @Marting:据我了解,您需要多一层嵌套:您提供给fromJson 的类必须“包含”ResultSet 类。
    • @nikow:感谢您的建议。我创建了一个名为 JsonContainer 的类,其成员变量 jsonContainer 类型为 ResultSet 并添加了 setter/getter。然后我调用了 JsonContainer data = new Gson().fromJson(content, JsonContainer.class);不幸的是 data.getJsonContainer() 仍然为空。我做错了什么?我还使用了 hakyer 发布的 JSON 片段
    • 是大小写问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-27
    • 2017-02-23
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多