Languages
[Edit]
EN

Java Jsoup - FIX for exception com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input in field name at [Source: java.io.StringReader@1725dc0f; line: 1, column: 1046939]

7 points
Created by:
JustMike
3491

1. Problem description

Code reproduction to get exception, json from my spring controller backend is quite big about 30 MB

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jsoup.Connection;
import org.jsoup.Jsoup;

import java.io.IOException;

public class JsoupHttpGetApp {

    public static void main(String[] args) throws IOException {

        String jsonBodyStr;
        try {
            jsonBodyStr = Jsoup.connect("http://localhost:8080/get-all-users")
                    .followRedirects(true)
                    .ignoreHttpErrors(true)
                    .userAgent("Mozilla/5.0 AppleWebKit/537.36 (KHTML," +
                            " like Gecko) Chrome/45.0.2454.4 Safari/537.36")
                    .method(Connection.Method.GET)
                    .timeout(10_000)
                    .ignoreContentType(true)
                    .execute()
                    .body();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        JsonNode rootNode = new ObjectMapper(new JsonFactory())
                .readTree(jsonBodyStr);

        System.out.println(rootNode);
    }
}

With above code I get this exception:

Exception in thread "main" com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: was expecting closing quote for a string value
 at [Source: java.io.StringReader@1a0dcaa; line: 1, column: 1046947]
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportInvalidEOF(ParserMinimalBase.java:483)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._finishString2(ReaderBasedJsonParser.java:2039)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._finishString(ReaderBasedJsonParser.java:2026)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.getText(ReaderBasedJsonParser.java:276)
	at com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer.deserializeObject(JsonNodeDeserializer.java:239)
	at com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer.deserializeArray(JsonNodeDeserializer.java:273)
	at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:72)
	at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:16)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789)
	at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:2372)

2. Solution

As we can see from stack trace the default size of json response in Jsoup is 1046947 bytes (1_046_947).

As fix for this we need to set bigger max body size.

Jsoup.connect("http://localhost:8080/get-all-users")
    // FIX - this line set max response size without limits
    // the only limit is your machine 
	.maxBodySize(0)
    // ...

From Jsoup.maxBodySize(0) java docs:

Set the maximum bytes to read from the (uncompressed) connection into the body, before the connection is closed, and the input truncated.

The default maximum is 1MB.

A max size of zero is treated as an infinite amount (bounded only by your patience and the memory available on your machine).

@param bytes number of bytes to read from the input before truncating
@return this Connection, for chaining

OR

Jsoup.connect("http://localhost:8080/get-all-users")
    // FIX - this line set max response size to 100 MB
	.maxBodySize(1_000_000 * 100) // 100 mb ~
    // ...

Full working code: 

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jsoup.Connection;
import org.jsoup.Jsoup;

import java.io.IOException;

public class JsoupHttpGetAppFIX {

    public static void main(String[] args) throws IOException {

        String jsonBodyStr;
        try {
            jsonBodyStr = Jsoup.connect("http://localhost:8080/get-all-users")

                    // FIX - this line set max response size without limit
                    // all our data will be fetched
                    .maxBodySize(0)

                    .followRedirects(true)
                    .ignoreHttpErrors(true)
                    .userAgent("Mozilla/5.0 AppleWebKit/537.36 (KHTML," +
                            " like Gecko) Chrome/45.0.2454.4 Safari/537.36")
                    .method(Connection.Method.GET)
                    .timeout(10_000)
                    .ignoreContentType(true)
                    .execute()
                    .body();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        JsonNode rootNode = new ObjectMapper(new JsonFactory())
                .readTree(jsonBodyStr);

        System.out.println(rootNode);
    }
}

 

Hey 👋
Would you like to know what we do?
  • Dirask is a friendly IT community for learners, professionals and hobbyists to share their knowledge and help each other in extraordinary easy way.
  • We welcome everyone,
    no matter what the experience,
    no matter how basic the question is,
    this community will help you.