This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
ElvishJerricco's profile picture

JSON API v2.0.1 for ComputerCraft

Started by ElvishJerricco, 10 November 2012 - 01:17 AM
ElvishJerricco #1
Posted 10 November 2012 - 02:17 AM
I've written a JSON parser! Simply give it a JSON block and it returns a lua value. Just use os.loadAPI() to load it up. Then call json.decode(). This is really useful because a lot of http servers (for example, the github api) use JSON to transmit data. So now you can actually use that data!

Example:


os.loadAPI("json")
str = http.get("http://www.someserver.com/").readAll()
obj = json.decode(str)
value = obj.thisVariableWasInTheJSONAndThisIsCoolerThanUsingStringGmatchToFindEverything

jsonstring = json.encode(obj)
sendThisToWhateverNeedsIt(jsonstring)

-- Also, it is very good for very readable config files.
prettystring = json.encodePretty(obj)
saveThisToAFile(prettystring)

And now introducing json.encodePretty(). Let's say you want the text to be pretty instead of small. json.encodePretty() will return formatted text instead of compact text. This is useful for things like config files where you want your users to be able to read the json easily.

Finally, json.decodeFromFile(). If you have some JSON in a file, this function will read it for you without you having to open the file and read it manually. Just do

local object = json.decodeFromFile("path/to/file")

pastebin get 4nRg9CHU json

Changelog:
Spoilerv2.0.1
  • Now errors when trying to encode a table that holds itself
v2.0
  • The encoder is much smaller/simpler
  • The decoder is a bit smarter
  • The decoder now correctly handles JSON that incorrectly puts nulls in (ehem… github API)
  • There is now a decodeFromFile function.
  • Because of the encoder rewrite, it is now half as long. From 396 lines to 191
v1.2
  • Added encodePretty
v1.1
  • Added encoding
v1.0
  • Initial release
gknova61 #2
Posted 10 November 2012 - 04:30 PM
Nice job, guy! =D
ElvishJerricco #3
Posted 10 November 2012 - 05:16 PM

I can't be sure but you appear to be trying to be condescending, as if what I've done is worthless because it's been done before… I guess people can't make their own implementations of anything anymore… But seeing as nothing like this is on the CC forums I figured I'd be alright to post it.
zekesonxx #4
Posted 11 November 2012 - 04:34 PM
-snip-

Fixed, nevermind.
Kilobyte #5
Posted 14 November 2012 - 10:47 AM
hey, mind if i add this to KilOS? (link is in my signature and ofc i'll credit you)
also this might better fit into the apis category :P/>/>
Orwell #6
Posted 14 November 2012 - 11:24 AM
I think you did a great job on this. It seems to be quite good. Even if it has been implemented before, there are numerous reasons to make it again. The most important one for me is simply developing your own skill set.
ElvishJerricco #7
Posted 17 November 2012 - 11:28 AM
hey, mind if i add this to KilOS? (link is in my signature and ofc i'll credit you)
also this might better fit into the apis category :)/>/>

I don't mind you using this at all. I actually quite like the KilOS concept (UNIX and stuffs) so yea go ahead and use it.
And yea i realize this would have been better suited there but it's too late now.

I think you did a great job on this. It seems to be quite good. Even if it has been implemented before, there are numerous reasons to make it again. The most important one for me is simply developing your own skill set.

I made sure to build it to the best of my ability. The only info i had was json.org which merely explains the format =P
Kilobyte #8
Posted 17 November 2012 - 11:45 AM
I don't mind you using this at all. I actually quite like the KilOS concept (UNIX and stuffs) so yea go ahead and use it.
And yea i realize this would have been better suited there but it's too late now.
Will be in next version
Orwell #9
Posted 17 November 2012 - 02:07 PM
*snip*
I made sure to build it to the best of my ability. The only info i had was json.org which merely explains the format =P
I made a JSON parser myself once, and I used the RFC: https://www.ietf.org/rfc/rfc4627.txt . Is this more detailed than the info you had? :)/>/>
ElvishJerricco #10
Posted 17 November 2012 - 05:06 PM
*snip*
I made sure to build it to the best of my ability. The only info i had was json.org which merely explains the format =P
I made a JSON parser myself once, and I used the RFC: https://www.ietf.org/rfc/rfc4627.txt . Is this more detailed than the info you had? :)/>/>

They both just describe the format. Neither's really more detailed. I was just pointing that out because I know there's a lot of people on the CC Forums that need to copy paste a lot of their code. I don't like to do that kind of programming.
CoolisTheName007 #11
Posted 08 December 2012 - 11:22 AM
Will test this later, seems like it's a good way to make readable config files!!! :D/>
ElvishJerricco #12
Posted 01 February 2013 - 03:08 PM
Updated. I added encodePretty. It's really useful for config files (that's why I made it)
Skullblade #13
Posted 01 February 2013 - 03:58 PM
not a big deal but FYI this should be in the APIs section ;)/>
nice job though
ElvishJerricco #14
Posted 01 February 2013 - 04:05 PM
not a big deal but FYI this should be in the APIs section ;)/>
nice job though

Yea I wasn't thinking when I posted this. Not sure how to move it though =P
theoriginalbit #15
Posted 01 February 2013 - 04:06 PM
Yea I wasn't thinking when I posted this. Not sure how to move it though =P
Click the report button and say something like "Posted in wrong section, please move to API's and Utilities"
ElvishJerricco #16
Posted 01 February 2013 - 04:11 PM
Yea I wasn't thinking when I posted this. Not sure how to move it though =P
Click the report button and say something like "Posted in wrong section, please move to API's and Utilities"

Ah. Thanks
Lyqyd #17
Posted 01 February 2013 - 04:22 PM
Moved to APIs and Utilities per user request.
ElvishJerricco #18
Posted 12 June 2013 - 05:37 AM
New update v2.0: Completely rewrote the encoder. Much simpler now. The decoder has been coded a bit more smartly, and it handles the technically illegal null value. There is now a decodeFromFile function. Oh and I should mention it's half as long now because of the encoder rewrite. Went from 396 lines to 191
Martin2789 #19
Posted 11 February 2014 - 03:37 PM
Nice Api you have there i get it to work with easy json like:

		{
			"firstline": "John",
			"secline": "Doe",
			"txtcol": "colors.white",
			"backcol": "colors.blue"
		}
with

os.loadAPI("json")
str = http.get("http://www.someserver.com/").readAll()
obj = json.decode(str)
print(obj.firstline)
but with complicated json like:


{
	"monitornorth": [
		{
			"firstline": "John",
			"secline": "Doe",
			"txtcol": "colors.white",
			"backcol": "colors.blue"
		}
	]
}


os.loadAPI("json")
str = http.get("http://www.someserver.com/").readAll()
obj = json.decode(str)
print(obj.monitornorth.firstline)
What am i do wrong?
EDIT:
Take a look at that piece of JSON again. monitornorth is an array with one object in it. That object is the first thing in monitornorth, so this is how you access it:
print(obj.monitornorth[1].firstline)
Thank you LBPHacker ;)/>
Edited on 14 February 2014 - 10:19 AM
daphee #20
Posted 20 June 2014 - 05:09 PM
Thank you for this nice lib. I've used it successfully on numerous projects.
This time it fails to decode this string

{"success":true,"code":0,"error":"","data":{"clientId":"testClient","requestId":"1","data":{"method":"get_redstone","side":"right"}}}
It fails with "json:167: attempt to index ? (a nil value)"
ElvishJerricco #21
Posted 21 June 2014 - 10:48 AM
Thank you for this nice lib. I've used it successfully on numerous projects.
This time it fails to decode this string

{"success":true,"code":0,"error":"","data":{"clientId":"testClient","requestId":"1","data":{"method":"get_redstone","side":"right"}}}
It fails with "json:167: attempt to index ? (a nil value)"

Fixed it! The issue was the empty string. It failed to handle that properly. Not sure why the pattern I used before didn't work with it but the new one does.
Edited on 21 June 2014 - 08:48 AM
daphee #22
Posted 22 June 2014 - 08:32 PM
Great! Thanks!
NightmareInfinity #23
Posted 26 March 2015 - 04:00 PM
is there a way to get the compact json from a website that is compacted and save it as a pretty string?
ElvishJerricco #24
Posted 26 March 2015 - 08:24 PM
is there a way to get the compact json from a website that is compacted and save it as a pretty string?

There's no straight conversion function, but you could do json.encodePretty(json.decode(str))
Lupus590 #25
Posted 03 May 2015 - 09:02 PM
For your records, Hive is now using this for it's github updating.

I hope you are ok with us redistributing your code,
Edited on 03 May 2015 - 07:03 PM
NightmareInfinity #26
Posted 22 May 2015 - 06:26 PM
is there a way to get the compact json from a website that is compacted and save it as a pretty string?

There's no straight conversion function, but you could do json.encodePretty(json.decode(str))
Im so dumb. I couldn't figure that out :P/>
flaghacker #27
Posted 23 May 2015 - 03:12 PM
Looks neat, and your code is really clean. One little mistake, your forgot to close the file in your decodeFromFile function.
manu_03 #28
Posted 28 July 2015 - 12:46 PM
Is that OK if I use it in MocOS installer and implement it within the internal APIs?
Stekeblad #29
Posted 14 January 2016 - 02:50 PM
I am using this very useful API in my program FluxedSeeds to decode the json file I download from gitHub
Pyuu #30
Posted 07 February 2016 - 03:34 AM
This API breaks when you do something like:

{
"Version": "1.0"
}

But works when:

{"Version": "1.0"}

Annoying for formatting.
Also, as a bug report from my OS (in which I'm heavily utilizing JSON), json.decodeFromFile doesn't close the file handle and causes unpredictable bugs.

Also, as another bug: You cannot JSON encode a string that contains the JSON api. Why? Because:

local controls = {["\n"]="\\n", ["\r"]="\\r", ["\t"]="\\t", ["\b"]="\\b", ["\f"]="\\f", ["\""]="\\\"", ["\\"]="\\\\"}

Turns into:

local controls = {["\
"]="\\
", ["\
"]="\\
", ["\ "]="\\ ", ["\"]="\\", [""]="\", ["\""]="\\\"", ["\\"]="\\\\"}

One way to get around this is to convert entire files to hexadecimal before Encode/decode.
Edited on 07 February 2016 - 04:06 AM
ElvishJerricco #31
Posted 14 February 2016 - 07:02 PM
I cannot replicate the first problem.

The second is caused by some really lazy string handling on my part. You really shouldn't be transferring code in Json but that's beside the point =P What I wrote works for any normal use case of json, but for something like this it broke. I'll get to fixing it.
ElvishJerricco #32
Posted 14 February 2016 - 07:26 PM
Fixed. Let me know if issues persist.
kd8lvt #33
Posted 15 February 2016 - 04:43 PM
Hello! My Twitch.tv interfacing api depends on your JSON api, and it really is great and easy to use, however, with the newest version of your api, whenever a new computer downloads the JSON api (I have it auto downloading from your pastebin) the computer locks up, then reboots. No error message, and it has no reason to do it either, it seems. So, for now I am reuploading an older version while I hope and pray that this magically gets fixed. I'm sorry I can't provide more details on the matter other than "the computer locks up, then reboots". If I could, I would.
Thanks!
~Kd
[Edit] I am using json.decode, if that helps.
Edited on 15 February 2016 - 03:44 PM
Lupus590 #34
Posted 15 February 2016 - 04:53 PM
Hello! My Twitch.tv interfacing api depends on your JSON api, and it really is great and easy to use, however, with the newest version of your api, whenever a new computer downloads the JSON api (I have it auto downloading from your pastebin) the computer locks up, then reboots. No error message, and it has no reason to do it either, it seems. So, for now I am reuploading an older version while I hope and pray that this magically gets fixed. I'm sorry I can't provide more details on the matter other than "the computer locks up, then reboots". If I could, I would.
Thanks!
~Kd
[Edit] I am using json.decode, if that helps.

it's possible that the pastebin change has caused this problem. Show us your download script.
ElvishJerricco #35
Posted 15 February 2016 - 09:44 PM
Hello! My Twitch.tv interfacing api depends on your JSON api, and it really is great and easy to use, however, with the newest version of your api, whenever a new computer downloads the JSON api (I have it auto downloading from your pastebin) the computer locks up, then reboots. No error message, and it has no reason to do it either, it seems. So, for now I am reuploading an older version while I hope and pray that this magically gets fixed. I'm sorry I can't provide more details on the matter other than "the computer locks up, then reboots". If I could, I would.
Thanks!
~Kd
[Edit] I am using json.decode, if that helps.

Weird. Worked when I tested it. But I only tested it with the C, command line version of Lua. Didn't try it in Minecraft.
ElvishJerricco #36
Posted 15 February 2016 - 09:53 PM
Got it. Somehow my testing didn't reveal a flaw in the string parsing. Fixed now.
Gumball #37
Posted 21 June 2016 - 04:43 AM
May I use this in one of my projects? It's basically a bridge between MySQL querying and CCLua, and it outputs your query's rows as JSON, and I was wondering if I could put it directly into my program
Gumball #38
Posted 21 June 2016 - 05:30 AM
For now I will probably just give a link to this topic, so that I do not distribute your program directly.
Steampunk_Sam #39
Posted 17 November 2016 - 04:13 PM
Hello,
This API is a fantastic addition for CC and I have started using it alongside my webserver for cross-game data transfer,

However I am running into a "Invalid escape character" error when it tries to parse the following:


{
    "status": true,
    "file": {
	    "name": "MC_chat",
	    "created_at": "2016-11-17 16:08:19",
	    "created_by": "N\/A",
	    "private": "0",
	    "rows": [
		    {
			    "text": "hello",
			    "created_at": "2016-11-17 17:11:49",
			    "created_by": "N\/A"
		    }
	    ]
    }
}

Any help would be much appreciated, I can also supply you (in private) usable links to my web api that I am retrieving the json string from for testing purposes.

Skype: SammyT291
Im always sitting in TeamSpeak at ts.wizry.net

All the best,
Sam.
SquidDev #40
Posted 17 November 2016 - 09:36 PM
-snip-

The API doesn't support "\/" as an escape character. If you add decodeControls["\\/"] = "/" on line 95 then everything should decode correctly.
Edited on 17 November 2016 - 08:36 PM
jonny190 #41
Posted 10 July 2017 - 12:03 AM
I'm trying to use obj.media_series_title but its outputting nothing, is there a way to use underscores?
Lignum #42
Posted 10 July 2017 - 12:26 AM
I'm trying to use obj.media_series_title but its outputting nothing, is there a way to use underscores?

That should work, so the problem is most likely somewhere else. Post the rest of the relevant code, please.

Either way, an idiotproof method that works with any string is to use [] to index obj:

obj["media_series_title"]
jonny190 #43
Posted 10 July 2017 - 06:28 PM
Dont Laugh too hard at my lack on coding ability

while true do
monitor = peripheral.wrap("back")
os.loadAPI("json")
str = http.get("https://home.daveys.xyz/api/states/media_player.firetv").readAll()
obj = json.decode(str)
monitor.clear()
monitor.setCursorPos(1,2)
monitor.write("Kodi is = ")
monitor.write(obj.state)
monitor.setCursorPos(1,4)
monitor.write("Kodi is playing", obj.media_series_title)
os.sleep( 3 )
term.clear()
monitor.clear()
monitor.setCursorPos(1,2)
sleep(0.05)
end
Edited on 10 July 2017 - 05:39 PM
Lignum #44
Posted 10 July 2017 - 06:43 PM
Dont Laugh too hard at my lack on coding ability

Oh, don't worry, there's significantly worse to be found around here.

That code looks fine to me, though. Does the monitor.write(obj.state) bit work? This is odd because if media_series_title wasn't indexed properly, it would write "nil" on the screen, not nothing, unless it's out of bounds for some reason. Are you sure the server is returning correct json? You might want to put print(str) after you http.get it to ensure that it's correct.
jonny190 #45
Posted 10 July 2017 - 07:16 PM
good to know,

The Webserver outputs:
"attributes": {"entity_picture": "/api/media_player_proxy/media_player.firetv?token=17f0d625441c059b681a532151a980af4dec61f14ccccaca413a9ec59646168d&cache=c61e3", "friendly_name": "FireTV", "is_volume_muted": false, "media_album_name": "", "media_content_id": {"unknown": ""}, "media_content_type": "tvshow", "media_duration": 1270, "media_episode": 15, "media_season": 1, "media_series_title": "American Dad!", "media_title": "American Dad S01E15", "supported_features": 55103, "volume_level": 1.0}, "entity_id": "media_player.firetv", "last_changed": "2017-07-10T18:42:20.419488+00:00", "last_updated": "2017-07-10T18:42:20.419488+00:00", "state": "playing"}

and the Monitor shows:
Edited on 10 July 2017 - 06:13 PM
jonny190 #46
Posted 10 July 2017 - 08:13 PM
Sorted it, looks like i forgot about the initial attributes section, changed it to obj.attributes.media_series_title and everything works no problem :D/>

Can this API be used to send commands in JSON?
Lignum #47
Posted 10 July 2017 - 11:04 PM
Can this API be used to send commands in JSON?

I'm not sure about what exactly you mean, but you can use json.encode to turn any table into a JSON-encoded string. Though, if you mean a literal Minecraft server command, you should use textutils.serialiseJSON, since the format isn't actually entirely JSON, it's slightly different.
Bomb Bloke #48
Posted 11 July 2017 - 01:36 AM
The alternate format is referred to as a data tag.
jonny190 #49
Posted 11 July 2017 - 11:16 PM
Can this API be used to send commands in JSON?

I'm not sure about what exactly you mean, but you can use json.encode to turn any table into a JSON-encoded string. Though, if you mean a literal Minecraft server command, you should use textutils.serialiseJSON, since the format isn't actually entirely JSON, it's slightly different.

Im trying to use RESTful API (https://home-assista...opers/rest_api/) for home assistant to make a minecraft button turn on a light in real life

So i'll be trying to call http://192.168.5.149:8123/api/services/switch/turn_on


{"entity_id": "switch.christmas_lights"}

Thanks,
Jonny
Edited on 11 July 2017 - 09:30 PM
Lignum #50
Posted 11 July 2017 - 11:28 PM
That's fairly straight forward. Simply make a table containing the request data, encode it, and then pass it as the POST body to http.post:

local request = {
  entity_id = "switch.christmas_lights"
}

local response = http.post("http://192.168.5.149:8123/api/services/switch/turn_on", json.encode(request))
response.close()
CRUGG #51
Posted 31 May 2019 - 10:02 AM
Hey there. I have a little Problem (it's probably something on my side), but could anyone help me?

packageUrl = http.get("https://ploxion.github.io/plx-ppm-packages/packages.json").readAll()
packageObj = json.decode(packageUrl)
value = packageObj[0].name
print(value)
This code doesn't work. What this should do is to print the name of the first Element in the JSON (https://ploxion.github.io/plx-ppm-packages/packages.json)
SquidDev #52
Posted 31 May 2019 - 10:14 AM
This code doesn't work. What this should do is to print the name of the first Element in the JSON (https://ploxion.gith...s/packages.json)
The top level object is an object, rather than an array - you'd need to do packageObj.luaide.name.
CRUGG #53
Posted 31 May 2019 - 10:16 AM
This code doesn't work. What this should do is to print the name of the first Element in the JSON (https://ploxion.gith...s/packages.json)
The top level object is an object, rather than an array - you'd need to do packageObj.luaide.name.
Well, the problem with that is, that I want to go through all things with a for loop later. And the problem is, with an array I can't store any sub information. Is there any other way?
Bomb Bloke #54
Posted 01 June 2019 - 05:30 AM
Sounds like you're after a pairs loop.
CRUGG #55
Posted 01 June 2019 - 05:04 PM
I don't really understand the link you sent me…