The way the wrapper works is looking at the first argument.
If it's a string, it's assumed you want JSON converted into a RouterOS array (e.g. parse something from ([/tool/fetch...]->"data").
If it's array, then it assume you want JSON as a string (e.g. submitting to website via /tool/fetch)
Code: Select all
### $JSON <str | array>
# if first arg is RouterOS array type, it will convert to JSON as string
# if arg is string, it's assumed it's JSON, so parsed into RouterOS array
# note: nothing will be printed by default, so it must be used without something like :put [$JSON $myarray]
:global JSON
:set JSON do={
:global JSONLoads
:put [:typeof $JSONLoads]
:if ([:typeof $JSONLoads]="nothing") do={
# can comment out once file has been download, but will be downloading only once here anyway
/tool fetch url=https://raw.githubusercontent.com/Winand/mikrotik-json-parser/master/JParseFunctions
:import JParseFunctions
:delay 5s
}
:if ([:typeof $1]="str") do={
:local got
:if ([len [/file find name=$1]] > 0) do={
:global JSONLoads
:set $got [$JSONLoads [/file get $1 contents]]
:return $got
}
:set $got [$JSONLoads $1]
:return $got
}
:if ([:typeof $1]="array") do={
:local tojson do={
:local ret "{"
:local firstIteration true
:foreach k,v in=$1 do={
if ($firstIteration) do={
:set $ret ($ret . "\"".$k . "\":")
} else={
:set $ret ($ret . "," . "\"". $k . "\":")
};
:set $firstIteration false
:local type [:typeof $v]
:if ($type = "array") do={
:set $ret ($ret . [$tojson $v])
} else={
:if ($type = "str" || $type = "id" || $type = "time" || $type = "ip" || $type = "ipv6") do={
:set $ret ($ret . "\"" . $v . "\"")
} else {
:set $ret ($ret . $v )
};
};
};
:set $ret ($ret . "}")
:return $ret;
};
:return [$tojson $1]
}
:error "Bug: Unhandled code path"
}
Also, sometime the request needs to be URLEncoded. RouterOS has a built-in v7.12 to do this. But for completeness here, here is some lightly-modified, but now legacy @rextended code that does it. This takes a RouterOS string as first argument to function, and then returns the URLencoded string for potential use in building a URL for /tool/fetch url="...":
Code: Select all
# from https://forum.mikrotik.com/viewtopic.php?p=670983&hilit=urlencode#p885685
:global URLENCODE
:set URLENCODE do={
:local Chars {" "="%20";"!"="%21";"#"="%23";"%"="%25";"&"="%26";"'"="%27";"("="%28";")"="%29";"*"="%2A";"+"="%2B";","="%2C";"/"="%2F";":"="%3A";";"="%3B";"<"="%3C";"="="%3D";">"="%3E";"@"="%40";"["="%5B";"]"="%5D";"^"="%5E";"`"="%60";"{"="%7B";"|"="%7C";"}"="%7D"}
:set ($Chars->"\07") "%07"
:set ($Chars->"\0A") "%0A"
:set ($Chars->"\0D") "%0D"
:set ($Chars->"\22") "%22"
:set ($Chars->"\24") "%24"
:set ($Chars->"\3F") "%3F"
:set ($Chars->"\5C") "%5C"
:local URLEncodeStr
:local Char
:local EncChar
:for i from=0 to=([:len $1]-1) do={
:set Char [:pick $1 $i]
:set EncChar ($Chars->$Char)
:if (any $EncChar) do={
:set URLEncodeStr "$URLEncodeStr$EncChar"
} else={
:set URLEncodeStr "$URLEncodeStr$Char"
}
}
:return $URLEncodeStr
}
Finally if RouterOS array to YAML output is needed, see viewtopic.php?p=1025335 . This becomes handy to VIEW JSON on RouterOS in more understand manner. So you can chain them for output
Code: Select all
:put [$YAML [$JSON ($fetchResults->"data")]