Other [B4X] quiz: Json prettifier

Erel

B4X founder
Staff member
Licensed User
Longtime User
Task: You have a compact json string and you want to understand its structure.
You can of course use this nice tool: https://b4x.com:51041/json/index.html
However the challenge is to log the "pretty" format of this json string with a single line of code.
B4X:
    Dim s As String = $"{"glossary":{"title":"example glossary","GlossDiv":{"GlossList":{"GlossEntry":{"GlossTerm":"Standard Generalized Markup Language","GlossSee":"markup","SortAs":"SGML","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"ID":"SGML","Acronym":"SGML","Abbrev":"ISO 8879:1986"}},"title":"S"}}}"$
 

udg

Expert
Licensed User
Longtime User
B4X:
Log(s.as(JSON).ToMap.As(JSON).ToString)
 
Last edited:
Upvote 2
Solution

udg

Expert
Licensed User
Longtime User
Yes.
My first thought was: Log(s.as(JSON).ToString)
which in my mind meant "look at 's' as a JSON string then apply the beautifier", but it showed error:
java.lang.RuntimeException: Only Maps and Lists are supported

That lead to the idea that 's' wasn't seen as a valid json map, so the concatenation you see in my solution:
- first obtain a valid map
- then cast it to a json to be passed to the beautifier
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
?
B4X:
    Dim s As String = $"{"glossary":{"title":"example glossary","GlossDiv":{"GlossList":{"GlossEntry":{"GlossTerm":"Standard Generalized Markup Language","GlossSee":"markup","SortAs":"SGML","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"ID":"SGML","Acronym":"SGML","Abbrev":"ISO 8879:1986"}},"title":"S"}}}"$
    Log(s.as(JSON).ToMap.As(JSON).ToString) 'Format Pretty
    Log(s.as(JSON).ToMap.As(JSON).ToCompactString) 'Format Compact
 
Upvote 0

cklester

Well-Known Member
Licensed User
The solution chokes for me on this (seemingly valid) JSON:

B4X:
[{"exchange":"binance","bestCaseFee":0.00015,"worstCaseFee":0.001,"icon":"https://assets.shrimpy.io/exchanges/binance.png"},{"exchange":"binanceus","bestCaseFee":0.001,"worstCaseFee":0.001,"icon":"https://assets.shrimpy.io/exchanges/binanceus.png"},{"exchange":"bittrex","bestCaseFee":0,"worstCaseFee":0.0025,"icon":"https://assets.shrimpy.io/exchanges/bittrex.png"},{"exchange":"bittrexinternational","bestCaseFee":0,"worstCaseFee":0.0025,"icon":"https://assets.shrimpy.io/exchanges/bittrexinternational.png"},{"exchange":"kucoin","bestCaseFee":0.000125,"worstCaseFee":0.001,"icon":"https://assets.shrimpy.io/exchanges/kucoin.png"},{"exchange":"coinbasepro","bestCaseFee":0,"worstCaseFee":0.003,"icon":"https://assets.shrimpy.io/exchanges/coinbasepro.png"},{"exchange":"poloniex","bestCaseFee":0,"worstCaseFee":0.0025,"icon":"https://assets.shrimpy.io/exchanges/poloniex.png"},{"exchange":"kraken","bestCaseFee":0,"worstCaseFee":0.0026,"icon":"https://assets.shrimpy.io/exchanges/kraken.png"},{"exchange":"bibox","bestCaseFee":0.0005,"worstCaseFee":0.001,"icon":"https://assets.shrimpy.io/exchanges/bibox.png"},{"exchange":"gemini","bestCaseFee":0,"worstCaseFee":0.0035,"icon":"https://assets.shrimpy.io/exchanges/gemini.png"},{"exchange":"huobiglobal","bestCaseFee":0.00015,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/huobiglobal.png"},{"exchange":"hitbtc","bestCaseFee":-0.001,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/hitbtc.png"},{"exchange":"bitmart","bestCaseFee":0.00015,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/bitmart.png"},{"exchange":"bitstamp","bestCaseFee":0,"worstCaseFee":0.005,"icon":"https://assets.shrimpy.io/exchanges/bitstamp.png"},{"exchange":"okex","bestCaseFee":-0.0001,"worstCaseFee":0.0015,"icon":"https://assets.shrimpy.io/exchanges/okex.png"},{"exchange":"bitfinex","bestCaseFee":0,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/bitfinex.png"},{"exchange":"ftxus","bestCaseFee":0,"worstCaseFee":0.004,"icon":"https://assets.shrimpy.io/exchanges/ftxus.png"},{"exchange":"ftx","bestCaseFee":0,"worstCaseFee":0.0007,"icon":"https://assets.shrimpy.io/exchanges/ftx.png"},{"exchange":"cexio","bestCaseFee":0,"worstCaseFee":0.004,"icon":"https://assets.shrimpy.io/exchanges/cexio.png"},{"exchange":"gateio","bestCaseFee":0,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/gateio.png"}]

Trying to use it like this:

B4X:
    Try
        msgJSON = msg.As(JSON).ToMap.As(JSON).ToString
    Catch
        msgJSON = "INVALID JSON DETECTED!" & CRLF & CRLF & msg
        Log(LastException)
    End Try

That same JSON works fine in the online JSON parser.
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
?
START AND END = [] = ToList
START AND END = {} = ToMap

B4X:
    Dim s As String = $"[{"exchange":"binance","bestCaseFee":0.00015,"worstCaseFee":0.001,"icon":"https://assets.shrimpy.io/exchanges/binance.png"},{"exchange":"binanceus","bestCaseFee":0.001,"worstCaseFee":0.001,"icon":"https://assets.shrimpy.io/exchanges/binanceus.png"},{"exchange":"bittrex","bestCaseFee":0,"worstCaseFee":0.0025,"icon":"https://assets.shrimpy.io/exchanges/bittrex.png"},{"exchange":"bittrexinternational","bestCaseFee":0,"worstCaseFee":0.0025,"icon":"https://assets.shrimpy.io/exchanges/bittrexinternational.png"},{"exchange":"kucoin","bestCaseFee":0.000125,"worstCaseFee":0.001,"icon":"https://assets.shrimpy.io/exchanges/kucoin.png"},{"exchange":"coinbasepro","bestCaseFee":0,"worstCaseFee":0.003,"icon":"https://assets.shrimpy.io/exchanges/coinbasepro.png"},{"exchange":"poloniex","bestCaseFee":0,"worstCaseFee":0.0025,"icon":"https://assets.shrimpy.io/exchanges/poloniex.png"},{"exchange":"kraken","bestCaseFee":0,"worstCaseFee":0.0026,"icon":"https://assets.shrimpy.io/exchanges/kraken.png"},{"exchange":"bibox","bestCaseFee":0.0005,"worstCaseFee":0.001,"icon":"https://assets.shrimpy.io/exchanges/bibox.png"},{"exchange":"gemini","bestCaseFee":0,"worstCaseFee":0.0035,"icon":"https://assets.shrimpy.io/exchanges/gemini.png"},{"exchange":"huobiglobal","bestCaseFee":0.00015,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/huobiglobal.png"},{"exchange":"hitbtc","bestCaseFee":-0.001,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/hitbtc.png"},{"exchange":"bitmart","bestCaseFee":0.00015,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/bitmart.png"},{"exchange":"bitstamp","bestCaseFee":0,"worstCaseFee":0.005,"icon":"https://assets.shrimpy.io/exchanges/bitstamp.png"},{"exchange":"okex","bestCaseFee":-0.0001,"worstCaseFee":0.0015,"icon":"https://assets.shrimpy.io/exchanges/okex.png"},{"exchange":"bitfinex","bestCaseFee":0,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/bitfinex.png"},{"exchange":"ftxus","bestCaseFee":0,"worstCaseFee":0.004,"icon":"https://assets.shrimpy.io/exchanges/ftxus.png"},{"exchange":"ftx","bestCaseFee":0,"worstCaseFee":0.0007,"icon":"https://assets.shrimpy.io/exchanges/ftx.png"},{"exchange":"cexio","bestCaseFee":0,"worstCaseFee":0.004,"icon":"https://assets.shrimpy.io/exchanges/cexio.png"},{"exchange":"gateio","bestCaseFee":0,"worstCaseFee":0.002,"icon":"https://assets.shrimpy.io/exchanges/gateio.png"}]"$
    Log(s.as(JSON).ToList.As(JSON).ToString) 'Format Pretty
 
Upvote 0

cklester

Well-Known Member
Licensed User
That's a solution to a different problem. What if I don't know what the JSON is?
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
That's a solution to a different problem. What if I don't know what the JSON is?
B4X:
Sub IsJson(json As String) As Boolean
    Return Regex.IsMatch($"[{\[]{1}([,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]|".*?")+[}\]]{1}"$, json.Trim) And json.Length > 2
End Sub
 
Upvote 0

cklester

Well-Known Member
Licensed User
OK, I'll just do it this way:

B4X:
    If msg.IndexOf("[") = 0 Then
        msgJSON = msg.as(JSON).ToList.As(JSON).ToString
    Else
        msgJSON = msg.as(JSON).ToMap.As(JSON).ToString
    End If
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
Button Parse Json Tree

B4X:
Sub btnParse_Action
    Try
        Dim parser As JSONParser
        parser.Initialize(txtJson.Text)
        tree.Root.Children.Clear
        Dim squareBracketFound As Boolean
        'check whether we need to call NextArray or NextObject
        For i = 0 To txtJson.Text.Length
            If txtJson.Text.CharAt(i) = "[" Then
                squareBracketFound = True
                Exit
            Else If txtJson.Text.CharAt(i) = "{" Then
                Exit
            End If
        Next
        Dim code As StringBuilder
        code.Initialize
        code.Append("Dim parser As JSONParser").Append(CRLF)
        code.Append("parser.Initialize(<text>)").Append(CRLF)
        code.Append("Dim root As ")
        If squareBracketFound Then
            code.Append("List = parser.NextArray").Append(CRLF)
            BuildTree(parser.NextArray, tree.Root, code, "root", "", False, "")
        Else
            code.Append("Map = parser.NextObject").Append(CRLF)
            BuildTree(parser.NextObject, tree.Root, code, "root", "", False, "")
        End If
        txtCode.Text = code.ToString
    Catch
        msg.Show("Error parsing string:" & CRLF & LastException.Message, "")
    End Try
End Sub
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…