'Accessing json value using jsonpath?

I'm following the tutorial for using jsonpath (https://www.baeldung.com/guide-to-jayway-jsonpath) and using the endpoint https://api.binance.com/api/v3/exchangeInfo I'm attempting to parse the value LOT_SIZE, stepSize for the symbol TRXEUR. The specific piece of JSON contained in the returned payload is contained in:

{
"symbol": "TRXEUR",
"status": "TRADING",
"baseAsset": "TRX",
"baseAssetPrecision": 8,
"quoteAsset": "EUR",
"quotePrecision": 8,
"quoteAssetPrecision": 8,
"baseCommissionPrecision": 8,
"quoteCommissionPrecision": 8,
"orderTypes": [
"LIMIT",
"LIMIT_MAKER",
"MARKET",
"STOP_LOSS_LIMIT",
"TAKE_PROFIT_LIMIT"
],
"icebergAllowed": true,
"ocoAllowed": true,
"quoteOrderQtyMarketAllowed": true,
"isSpotTradingAllowed": true,
"isMarginTradingAllowed": false,
"filters": [
{
"filterType": "PRICE_FILTER",
"minPrice": "0.00010000",
"maxPrice": "1000.00000000",
"tickSize": "0.00010000"
},
{
"filterType": "PERCENT_PRICE",
"multiplierUp": "5",
"multiplierDown": "0.2",
"avgPriceMins": 5
},
{
"filterType": "LOT_SIZE",
"minQty": "1.00000000",
"maxQty": "90000000.00000000",
"stepSize": "1.00000000"
},
{
"filterType": "MIN_NOTIONAL",
"minNotional": "10.00000000",
"applyToMarket": true,
"avgPriceMins": 5
},
{
"filterType": "ICEBERG_PARTS",
"limit": 10
},
{
"filterType": "MARKET_LOT_SIZE",
"minQty": "0.00000000",
"maxQty": "904859.10069444",
"stepSize": "0.00000000"
},
{
"filterType": "MAX_NUM_ORDERS",
"maxNumOrders": 200
},
{
"filterType": "MAX_NUM_ALGO_ORDERS",
"maxNumAlgoOrders": 5
}
],
"permissions": [
"SPOT"
]
}

More specifically how to extract 1.00000000 from :

{
"filterType": "LOT_SIZE",
"minQty": "1.00000000",
"maxQty": "90000000.00000000",
"stepSize": "1.00000000"
}

Here is what I've written :

public class ParseJson {

    public static void main(String[] args) {

        try {
            URL url = new URL("https://api.binance.com/api/v3/exchangeInfo");
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuffer content = new StringBuffer();
            while ((inputLine = in.readLine()) != null) {
                content.append(inputLine);
            }
            in.close();

            final String jsonString = content.toString();
            List<Object> dataObject = JsonPath.parse(jsonString).read("symbols");
            dataObject.forEach(x -> {
                        if (x.toString().toUpperCase().contains("TRXEUR")) {
                            List<Object> lo = JsonPath.parse(x.toString()).read("symbol");

                        }
                    }

            );
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}

Which returns :

20:52:10.428 [main] DEBUG com.jayway.jsonpath.internal.path.CompiledPath - Evaluating path: $['symbols']
20:52:10.469 [main] DEBUG com.jayway.jsonpath.internal.path.CompiledPath - Evaluating path: $['symbol']
Exception in thread "main" com.jayway.jsonpath.PathNotFoundException: No results for path: $['symbol']
    at com.jayway.jsonpath.internal.path.EvaluationContextImpl.getValue(EvaluationContextImpl.java:133)
    at com.jayway.jsonpath.JsonPath.read(JsonPath.java:187)
    at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:102)
    at com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:89)
    at com.reactive.api.scenarios.ParseJson.lambda$main$0(ParseJson.java:37)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at com.reactive.api.scenarios.ParseJson.main(ParseJson.java:34)

Process finished with exit code 1

I can access the symbol TRXEUR and symbols is parsed but how to extract 1.00000000 from :

{
"filterType": "LOT_SIZE",
"minQty": "1.00000000",
"maxQty": "90000000.00000000",
"stepSize": "1.00000000"
}

?



Solution 1:[1]

From https://jsonpath.herokuapp.com/

$.filters[?(@.filterType=='LOT_SIZE')].stepSize

Solution 2:[2]

I may not need to cast to Object on the return type (for example List<Map<String, Object>>) and use Map instead but this works :

import com.jayway.jsonpath.JsonPath;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

public class ParseJson {

    public static void main(String[] args) {

        try {
            URL url = new URL("https://api.binance.com/api/v3/exchangeInfo");
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuffer content = new StringBuffer();
            while ((inputLine = in.readLine()) != null) {
                content.append(inputLine);
            }
            in.close();

            final String jsonString = content.toString();
            List<Map<String, Object>> items = JsonPath.parse(jsonString).read("symbols");
            items.forEach(m -> {
                if (m.get("symbol").toString().toUpperCase().equalsIgnoreCase("BTCEUR")) {
                    List<Map<String, Object>> m3 = (List<Map<String, Object>>) m.get("filters");
                    m3.forEach(m2 -> {
                        if (m2.get("filterType").toString().equalsIgnoreCase("LOT_SIZE")) {
                            System.out.println("Stepsize " + m2.get("stepSize"));
                        }
                    });
                }
            });

        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}

Prints :

22:47:25.070 [main] DEBUG com.jayway.jsonpath.internal.path.CompiledPath - Evaluating path: $['symbols']
Stepsize 0.00000100

Solution 3:[3]

Your origin question:

Object read = JsonPath.read(jsonString, "$.filters[?(@.filterType=='LOT_SIZE')].stepSize");

JSON from "https://api.binance.com/api/v3/exchangeInfo":

Object read = JsonPath.read(jsonString, "$.symbols[?(@.symbol=='BTCEUR')].filters[?(@.filterType=='LOT_SIZE')].stepSize");

In case you still want to use streams, ur second generic is Object so we do need to cast explisitly (List<Map<String, Object>>) :

String stepSize = items
        .stream()
        .filter(map -> "BTCEUR".equalsIgnoreCase(map.get("symbol").toString()))
        .map(map -> (List<Map<String, Object>>) map.get("filters"))
        .findFirst()
        .orElseThrow()
        .stream()
        .filter(map -> "LOT_SIZE".equalsIgnoreCase(map.get("filterType").toString()))
        .findFirst()
        .orElseThrow()
        .get("stepSize")
        .toString();

System.out.println(stepSize);

Solution 4:[4]

Your job is to find the value of stepSize where the symbols value is TRXEUR and filterType value is LOT_SIZE. But the code will be long and complicated if you use Java to do it.

Suggest you using SPL, an open-source Java package. Coding will be really easy and you only need one line:

A
1 =json(httpfile("https://api.binance.com/api/v3/exchangeInfo").read()).
symbols.select(symbol=="TRXEUR").filters.select(~.filterType=="LOT_SIZE").stepSize

SPL offers JDBC driver to be invoked by Java. Just store the above SPL script as getvalue.splx and invoke it in a Java application as you call a stored procedure:

…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st = con.prepareCall("call getvalue()");
st.execute();
…

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 cigien
Solution 2 blue-sky
Solution 3
Solution 4 LeoTaylor