programing

JSON 입력 스트림을 해석하는 방법

sourcejob 2023. 2. 8. 17:51
반응형

JSON 입력 스트림을 해석하는 방법

java를 사용하여 JSON 개체를 반환하는 URL을 호출하고 있습니다.

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

응답을 문자열 형식으로 변환하고 해석하려면 어떻게 해야 합니까?

InputStream을 변환하려면 Reader를 사용해야 합니다.

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으로 파생된다고 기재되어 있는 문서와 같습니다)

현재의 답변은 모두 입력 스트림을 조금씩 읽을 수 있는 것이 장점인 경우 JSON 전체를 메모리로 가져와도 괜찮다고 가정하고 있습니다.Json 파일 전체를 한 번에 읽는 것을 피하고 싶다면 잭슨 라이브러리를 사용하는 것이 좋습니다(개인적으로는 마음에 들지만 Gson과 같은 다른 사람들도 비슷한 기능을 가지고 있을 것입니다).

Jackson에서는 JsonParser를 사용하여 한 번에 한 섹션을 읽을 수 있습니다.다음은 반복기에서 JsonObjects 배열 읽기를 랩하는 코드의 예입니다.Jackson의 예만 보려면 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);
    }

}

메모리 사용량을 신경 쓰지 않는다면 파일 전체를 읽고 다른 답변에서 언급한 것처럼 하나의 큰 Json으로 해석하는 것이 분명 더 쉬울 것입니다.

이와 같이 InputStream의 toString 메서드를 사용할 수 없다는 지적에 대해서는http://https://stackoverflow.com/a/5445161/1304830 를 참조해 주세요.

제 정답은 다음과 같습니다.

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

Jackson Databind를 사용하는 경우(어느쪽입니까)Spring디폴트로는 를 사용합니다.HttpMessageConvertersObjectMapper.readTree(InputStream) API를 사용할 수 있습니다.예를들면,

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

Jackson을 사용하여 json 입력 스트림을 맵 또는 개체로 변환 http://jackson.codehaus.org/

json을 위한 다른 유용한 라이브러리도 있습니다. 구글에서 json java를 검색할 수 있습니다.

도서관을 이용하다.

  • 지손
  • 잭슨
  • JSON 라이브러리 중 하나일 수도 있습니다.

Gson을 사용한 Kotlin 버전

응답을 읽으려면 JSON:

val response = BufferedReader(
                   InputStreamReader(conn.inputStream, "UTF-8")
               ).use { it.readText() }

응답을 해석하기 위해 Gson을 사용할 수 있습니다.

val model = Gson().fromJson(response, YourModelClass::class.java)

이 예에서는 오브젝트 스트림에서 모든 오브젝트를 읽고 맵 대신 CustomObjects가 필요하다고 가정합니다.

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

답변은 잭슨을 사용하여 Json 객체의 어레이를 스트림 해석하고 Json Node를 객체로 변환하는 방법으로 구성되었습니다.

javax.json 사용을 권장합니다.Json 팩토리에서는 가능한 한 상세하지 않은 솔루션:

JsonObject json = Json.createReader(yourInputStream).readObject();

맛있게 드세요!

JSON 파일이 있는 경우 자산 폴더에 파일을 설정하고 이 코드를 사용하여 호출할 수 있습니다.

InputStream in = mResources.getAssets().open("fragrances.json"); 
// where mResources object from Resources class
{
    InputStream is = HTTPClient.get(url);
    InputStreamReader reader = new InputStreamReader(is);
    JSONTokener tokenizer = new JSONTokener(reader);
    JSONObject jsonObject = new JSONObject(tokenizer);
}

언급URL : https://stackoverflow.com/questions/6511880/how-to-parse-a-json-input-stream

반응형