Подтвердить что ты не робот

Как разобрать поток ввода JSON

Я использую java для вызова URL-адреса, который возвращает объект JSON:

url = new URL("my URl");
urlInputStream = url.openConnection().getInputStream();

Как я могу преобразовать ответ в строчную форму и проанализировать ее?

4b9b3361

Ответ 1

Я бы посоветовал вам использовать 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());

Я попытался in.toString(), но он возвращает:

getClass().getName() + '@' + Integer.toHexString(hashCode())

(например, документация говорит, что она выводится на toString из Object)

Ответ 2

Все текущие ответы предполагают, что все в порядке, чтобы вытащить весь JSON в память, где преимущество InputStream заключается в том, что вы можете прочитать ввод постепенно. Если вы хотите не читать весь Json файл сразу, я бы предложил использовать библиотеку Jackson (это мой личный фаворит, но я уверен, что другие, подобные Gson, имеют схожие функции).

С помощью Jackson вы можете использовать JsonParser для чтения одного раздела за раз. Ниже приведен пример кода, который я написал, который обертывает чтение массива JsonObjects в Iterator. Если вы просто хотите увидеть пример Джексона, посмотрите на методы 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 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);
    }

}

Если вы не заботитесь об использовании памяти, то, конечно, было бы легче прочитать весь файл и проанализировать его как один большой Json, как упоминалось в других ответах.

Ответ 3

использовать jackson для преобразования потока ввода json на карту или объект http://jackson.codehaus.org/

есть также и другие полезные библиотеки для json, вы можете google: json java

Ответ 4

Для тех, кто указал на то, что вы не можете использовать метод toString InputStream, как это, см. fooobar.com/questions/226/...:

Моим правильным ответом было бы следующее:

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());

Ответ 5

Использовать библиотеку.

  • GSON
  • Jackson
  • или одна из многих других библиотек JSON, которые находятся там.

Ответ 6

Если вы хотите использовать Jackson Databind (который Spring использует по умолчанию для своего HttpMessageConverters), вы можете использовать API ObjectMapper.readTree(InputStream). Например,

ObjectMapper mapper = new ObjectMapper();
JsonNode json = mapper.readTree(myInputStream);

Ответ 7

{
    InputStream is = HTTPClient.get(url);
    InputStreamReader reader = new InputStreamReader(is);
    JSONTokener tokenizer = new JSONTokener(reader);
    JSONObject jsonObject = new JSONObject(tokenizer);
}