Java 如何解析 JSON 输入流
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6511880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to parse a JSON Input stream
提问by Ritesh Mehandiratta
I am using java to call a url that returns a JSON object:
我正在使用 java 调用返回 JSON 对象的 url:
url = new URL("my URl");
urlInputStream = url.openConnection().getInputStream();
How can I convert the response into string form and parse it?
如何将响应转换为字符串形式并解析它?
回答by Penkov Vladimir
use Hymanson to convert json input stream to the map or object http://Hymanson.codehaus.org/
使用 Hymanson 将 json 输入流转换为地图或对象http://Hymanson.codehaus.org/
there are also some other usefull libraries for json, you can google: json java
还有一些其他有用的 json 库,你可以谷歌:json java
回答by Dunes
回答by Sudhir Bhojwani
{
InputStream is = HTTPClient.get(url);
InputStreamReader reader = new InputStreamReader(is);
JSONTokener tokenizer = new JSONTokener(reader);
JSONObject jsonObject = new JSONObject(tokenizer);
}
回答by Martin Christmann
I would suggest you have to use a Reader to convert your InputStream in.
我建议您必须使用 Reader 来转换您的 InputStream。
BufferedReader streamReader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
StringBuilder responseStrBuilder = new StringBuilder();
String inputStr;
while ((inputStr = streamReader.readLine()) != null)
responseStrBuilder.append(inputStr);
new JSONObject(responseStrBuilder.toString());
I tried in.toString() but it returns:
我试过 in.toString() 但它返回:
getClass().getName() + '@' + Integer.toHexString(hashCode())
(like documentation says it derives to toString from Object)
(就像文档说它从 Object 派生到 toString)
回答by Fr4nz
For those that pointed out the fact that you can't use the toString method of InputStream like this see https://stackoverflow.com/a/5445161/1304830:
对于那些指出您不能像这样使用 InputStream 的 toString 方法这一事实的人,请参阅https://stackoverflow.com/a/5445161/1304830:
My correct answer would be then :
我的正确答案是:
import org.json.JSONObject;
public static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\A");
return s.hasNext() ? s.next() : "";
}
...
JSONObject json = new JSONObject(convertStreamToString(url.openStream());
回答by BoostHungry
All the current answers assume that it is okay to pull the entire JSON into memory where the advantage of an InputStream is that you can read the input little by little. If you would like to avoid reading the entire Json file at once then I would suggest using the Hymanson library (which is my personal favorite but I'm sure others like Gson have similar functions).
所有当前的答案都假设可以将整个 JSON 拉入内存中,其中 InputStream 的优点是您可以一点一点地读取输入。如果您想避免一次读取整个 Json 文件,那么我建议使用 Hymanson 库(这是我个人最喜欢的,但我相信像 Gson 这样的其他库也有类似的功能)。
With Hymanson you can use a JsonParser to read one section at a time. Below is an example of code I wrote that wraps the reading of an Array of JsonObjects in an Iterator. If you just want to see an example of Hymanson, look at the initJsonParser, initFirstElement, and initNextObject methods.
使用 Hymanson,您可以使用 JsonParser 一次读取一个部分。下面是我编写的代码示例,该示例将读取 JsonObjects 数组的内容包装在迭代器中。如果您只想查看 Hymanson 的示例,请查看 initJsonParser、initFirstElement 和 initNextObject 方法。
public class JsonObjectIterator implements Iterator<Map<String, Object>>, Closeable {
private static final Logger LOG = LoggerFactory.getLogger(JsonObjectIterator.class);
private final InputStream inputStream;
private JsonParser jsonParser;
private boolean isInitialized;
private Map<String, Object> nextObject;
public JsonObjectIterator(final InputStream inputStream) {
this.inputStream = inputStream;
this.isInitialized = false;
this.nextObject = null;
}
private void init() {
this.initJsonParser();
this.initFirstElement();
this.isInitialized = true;
}
private void initJsonParser() {
final ObjectMapper objectMapper = new ObjectMapper();
final JsonFactory jsonFactory = objectMapper.getFactory();
try {
this.jsonParser = jsonFactory.createParser(inputStream);
} catch (final IOException e) {
LOG.error("There was a problem setting up the JsonParser: " + e.getMessage(), e);
throw new RuntimeException("There was a problem setting up the JsonParser: " + e.getMessage(), e);
}
}
private void initFirstElement() {
try {
// Check that the first element is the start of an array
final JsonToken arrayStartToken = this.jsonParser.nextToken();
if (arrayStartToken != JsonToken.START_ARRAY) {
throw new IllegalStateException("The first element of the Json structure was expected to be a start array token, but it was: " + arrayStartToken);
}
// Initialize the first object
this.initNextObject();
} catch (final Exception e) {
LOG.error("There was a problem initializing the first element of the Json Structure: " + e.getMessage(), e);
throw new RuntimeException("There was a problem initializing the first element of the Json Structure: " + e.getMessage(), e);
}
}
private void initNextObject() {
try {
final JsonToken nextToken = this.jsonParser.nextToken();
// Check for the end of the array which will mean we're done
if (nextToken == JsonToken.END_ARRAY) {
this.nextObject = null;
return;
}
// Make sure the next token is the start of an object
if (nextToken != JsonToken.START_OBJECT) {
throw new IllegalStateException("The next token of Json structure was expected to be a start object token, but it was: " + nextToken);
}
// Get the next product and make sure it's not null
this.nextObject = this.jsonParser.readValueAs(new TypeReference<Map<String, Object>>() { });
if (this.nextObject == null) {
throw new IllegalStateException("The next parsed object of the Json structure was null");
}
} catch (final Exception e) {
LOG.error("There was a problem initializing the next Object: " + e.getMessage(), e);
throw new RuntimeException("There was a problem initializing the next Object: " + e.getMessage(), e);
}
}
@Override
public boolean hasNext() {
if (!this.isInitialized) {
this.init();
}
return this.nextObject != null;
}
@Override
public Map<String, Object> next() {
// This method will return the current object and initialize the next object so hasNext will always have knowledge of the current state
// Makes sure we're initialized first
if (!this.isInitialized) {
this.init();
}
// Store the current next object for return
final Map<String, Object> currentNextObject = this.nextObject;
// Initialize the next object
this.initNextObject();
return currentNextObject;
}
@Override
public void close() throws IOException {
IOUtils.closeQuietly(this.jsonParser);
IOUtils.closeQuietly(this.inputStream);
}
}
If you don't care about memory usage, then it would certainly be easier to read the entire file and parse it as one big Json as mentioned in other answers.
如果您不关心内存使用情况,那么阅读整个文件并将其解析为其他答案中提到的一个大 Json 肯定会更容易。
回答by Somu
If you like to use Hymanson Databind(which Spring
uses by default for its HttpMessageConverters
), then you may use the ObjectMapper.readTree(InputStream)API. For example,
如果您喜欢使用Hymanson Databind(Spring
默认情况下为其使用HttpMessageConverters
),那么您可以使用ObjectMapper.readTree(InputStream)API。例如,
ObjectMapper mapper = new ObjectMapper();
JsonNode json = mapper.readTree(myInputStream);
回答by Sayed Saeed
if you have JSON file you can set it on assets folder then call it using this code
如果您有 JSON 文件,您可以将其设置在资产文件夹中,然后使用此代码调用它
InputStream in = mResources.getAssets().open("fragrances.json");
// where mResources object from Resources class
回答by stacker
This example reads all objects from a stream of objects, it is assumed that you need CustomObjects instead of a Map:
此示例从对象流中读取所有对象,假设您需要 CustomObjects 而不是 Map:
ObjectMapper mapper = new ObjectMapper();
JsonParser parser = mapper.getFactory().createParser( source );
if(parser.nextToken() != JsonToken.START_ARRAY) {
throw new IllegalStateException("Expected an array");
}
while(parser.nextToken() == JsonToken.START_OBJECT) {
// read everything from this START_OBJECT to the matching END_OBJECT
// and return it as a tree model ObjectNode
ObjectNode node = mapper.readTree(parser);
CustomObject custom = mapper.convertValue( node, CustomObject.class );
// do whatever you need to do with this object
System.out.println( "" + custom );
}
parser.close();
This answer was composed by using : Use Hymanson To Stream Parse an Array of Json Objectsand Convert JsonNode into Object
这个答案是由使用组成的:使用Hyman逊流解析一个 Json 对象数组并将JsonNode 转换为对象
回答by FarshidABZ
Kotlin version with Gson
带有 Gson 的 Kotlin 版本
to read the response JSON:
读取响应 JSON:
val response = BufferedReader(
InputStreamReader(conn.inputStream, "UTF-8")
).use { it.readText() }
to parse response we can use Gson:
要解析响应,我们可以使用 Gson:
val model = Gson().fromJson(response, YourModelClass::class.java)