There is a JSON string:

{"str1": "str1", "str2": "str2", "str3": { "str4": 1.3762, "str5": 1.9558, "srt6": 3.2623,}} 

It is necessary to write the contents of str3 in HashMap.

I tried it this way, but the compiler gives an error:

 Type type = new TypeToken<Map<String, Double>>(){}.getType(); Map<String, Double> myMap = gson.fromJson(bufferedReader, type); 

Mistake:

 java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $ 

Thanks a lot in advance!

    2 answers 2

    However, the JSON that you are processing does not quite correspond to what is in the post, since GSON swears that the first symbol sees the string and not the beginning of the object ( { ).

    • It is not the answer to the question. To leave your comments or ask the author to clarify, leave a comment to the appropriate post. - From the queue of checks - Vadizar
    • @Vadizar In this case, the problem is in the absence { , its addition should solve the problem. - gt22

    gt22 is right - you have JsonReader met a line under the hood, but not the expected { . In addition, srt6 has a hanging comma, which prevents parsing of a JSON document. And besides, your expected type seems to be aimed at the entire JSON document that does not correspond to this type (at the highest level there is no numerical value).

    But, nevertheless, there are two fundamentally different approaches to the solution of such issues: either use the JSON object model, or read data streams. Each has its own characteristics, advantages and disadvantages.

    In the first case (in the case of the object model), if it is assumed that the data size can be neglected due to their small size and parsing is cheap, you can simply read the JSON document as JsonObject and use it to get to str3 and deserialize its value as Map<String, Double> :

      final JsonObject jsonObject = gson.fromJson(bufferedReader, JsonObject.class); final JsonElement str3JsonElement = jsonObject.get("str3"); final Map<String, Double> values = gson.fromJson(str3JsonElement, stringToDoubleMapType); System.out.println(values); 

    If the size of the input data is large and the memory cannot be spent on parsing useless data, you need to read the input document as a stream of tokens, parsing the tokens manually. And already, based on a particular state, extract the value of str3 . Therefore, the implementation of such a parser is already more complicated:

     final JsonReader jsonReader = new JsonReader(bufferedReader); final Map<String, Double> values = extractValues(gson, jsonReader, "str3"); System.out.println(values); 
     private static Map<String, Double> extractValues(final Gson gson, final JsonReader jsonReader, final String expectedName) throws IOException { Map<String, Double> values = null; // убеждаемся, что первым токеном является { jsonReader.beginObject(); // и читаем все токены, пока не встретится } while ( jsonReader.peek() != END_OBJECT ) { // извлекаем имя свойства final String actualName = jsonReader.nextName(); if ( actualName.equals(expectedName) ) { // и если оно совпадает с expectedName (str3) -- проделегировать десериализацию Gson-у values = gson.fromJson(jsonReader, stringToDoubleMapType); } else { // иначе проигнорировать значение jsonReader.skipValue(); } } // убеждаемся, что объект был прочитан полностью jsonReader.endObject(); return values; } 

    In both cases, the stdout will display:

    {str4 = 1.3762, str5 = 1.9558, srt6 = 3.2623}