0

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"
}

?

6
  • Deleted the XPath tag as this question appears to have nothing to do with XPath. Commented May 8, 2021 at 21:00
  • The error message No results for path: $['symbol'] doesn't appear to match what I would expect to see - which is No results for path: $['symbols']. Does the code in the question align with the stack trace? There is no item called symbols in the JSON. Commented May 8, 2021 at 21:27
  • Instead of List<Object> dataObject = JsonPath.parse(jsonString).read("symbols");, use List<Map<String, String>> items = JsonPath.parse(jsonString).read("filters");. then you will have a list of maps that you can iterate through much more easily than trying to manipulate strings. Commented May 8, 2021 at 21:31
  • @andrewjames thanks, I'm posting an answer. Commented May 8, 2021 at 21:48
  • 1
    @symbols is in the rest payload response, I posted a snippet of the response. Commented May 8, 2021 at 21:58

4 Answers 4

1

From https://jsonpath.herokuapp.com/

$.filters[?(@.filterType=='LOT_SIZE')].stepSize
Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

0

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.