Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用流/对象方法将JSON解析为Jackson_Java_Json_Parsing_Jackson - Fatal编程技术网

Java 使用流/对象方法将JSON解析为Jackson

Java 使用流/对象方法将JSON解析为Jackson,java,json,parsing,jackson,Java,Json,Parsing,Jackson,我有一个JSON文件,它可以有多种类型 例如: { "dog": { "owner" : "John Smith", "name" : "Rex", "toys" : { "chewtoy" : "5", "bone" : "1" } }, "person": { "name" : "John Doe", "address" :

我有一个JSON文件,它可以有多种类型

例如:

{
    "dog": {
        "owner" : "John Smith",
        "name" : "Rex",
        "toys" : {
            "chewtoy" : "5",
            "bone" : "1"
        }
    },
    "person": {
        "name" : "John Doe",
        "address" : "23 Somewhere Lane"
    }
    // Further examples of dogs and people, and a few other types.
}
我想把它们解析成对象。例如,我想创建一个具有owner/name/toys属性的Dog对象,以及一个具有name/address属性的person对象,并使用Jackson从中读取和创建对象

订购很重要——例如,我需要知道雷克斯先于约翰·多伊。我更喜欢使用流式方法(即,将Rex读入并解析为Dog对象,使用它做一些事情,然后丢弃它,然后转到John Doe)。所以我需要一种基于流的方法


我不知道如何使用流读取API(按顺序进行)和ObjectMapper接口(按JSON创建Java对象)来实现这一点。

要做到这一点,您需要在工厂中使用对象映射器

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
...
private static ObjectMapper mapper = new ObjectMapper();
private static JsonFactory factory = mapper.getJsonFactory();
然后为输入创建一个解析器

JsonParser parser = factory.createJsonParser(in);
现在可以混合调用parser.nextToken()和parser.readValueAs(类c)。下面是一个从映射中获取类的示例:

Map<String, Class<?>> classMap = new HashMap<String, Class<?>>();
classMap.put("dog", Dog.class);
classMap.put("person", Person.class);

InputStream in = null;
JsonParser parser = null;
List<Object> results = new ArrayList<Object>();
try {
  in = this.getClass().getResourceAsStream("input.json");
  parser = factory.createJsonParser(in);
  parser.nextToken();// JsonToken.START_OBJECT
  JsonToken token = null;
  while( (token = parser.nextToken()) == JsonToken.FIELD_NAME ) {
    String name = parser.getText();
    parser.nextToken(); // JsonToken.START_OBJECT
    results.add(parser.readValueAs(classMap.get(name)));
  }
  // ASSERT: token = JsonToken.END_OBJECT
}
finally {
  IOUtils.closeQuietly(in);
  try {
    parser.close();
  }
  catch( Exception e ) {}
}
Map>();
classMap.put(“dog”,dog.class);
classMap.put(“person”,person.class);
InputStream in=null;
JsonParser=null;
列表结果=新建ArrayList();
试一试{
in=this.getClass().getResourceAsStream(“input.json”);
parser=factory.createJsonParser(in);
parser.nextToken();//JsonToken.START_对象
JsonToken token=null;
while((token=parser.nextToken())==JsonToken.FIELD\u NAME){
String name=parser.getText();
parser.nextToken();//JsonToken.START_对象
add(parser.readValueAs(classMap.get(name));
}
//ASSERT:token=JsonToken.END\u对象
}
最后{
安静地关闭(在);
试一试{
parser.close();
}
捕获(例外e){}
}

(1)您关于流或类似SAX的解析的问题是完全正确的+1.但是(2)如果在字典中排序很重要,那么您的数据设计得不好。JSON字典本质上是无序的。如果您需要订单,请使用数组并将类型(狗/人)信息编码为属性。数据源可能不可更改(不在我的控制之下)。当你说使用数组并对信息进行编码时,你的意思是手动执行吗?(通读所有标记并创建适当的对象,调用适当的setter)或者有没有办法使用Jackson实现这一点?我的意思是,如果顺序很重要,JSON数据应该以数组的形式出现,并且使用每个对象编码类型。但如果您不控制JSON数据,则无需担心——您将不得不按照您的建议处理流解析。:)我不知道你真正的问题的答案,尽管这里肯定会有其他人知道。但是要知道,不管是谁提出了这种JSON格式,都是在玩火。依赖字典中的键的顺序是非常脆弱的,更不用说它给那些试图处理它的人(你)带来的痛苦了——这与大多数工具的纹理背道而驰。谢谢你的回复。如果我确实更改了数据,以便将对象作为数组存储在中,那么是否可以执行流/对象映射器组合解析方法?我想我现在明白了。当我开始尝试这样做的时候,我很挣扎,因为我不知道我在哪个对象(“dog”或“person”),但是如果数据被格式化为一个数组,其中dog/person值作为“type”属性中的值,我就能够做到这一点。谢谢大家,回答得好。但是,如果您可以使用最新的Jackson库重写代码段,那就太好了。