Add sjson streaming example

Fixes #2209.
This commit is contained in:
Marcel Stör 2018-02-04 12:45:27 +01:00
parent f87d68ff8f
commit 555b5574a2
2 changed files with 77 additions and 2 deletions

View File

@ -21,6 +21,10 @@ anywhere else in your data structures. A suitable value might be `"\0"`.
When encoding a Lua object, if a function is found, then it is invoked (with no arguments) and the (single) returned value is encoded in the place of the function. When encoding a Lua object, if a function is found, then it is invoked (with no arguments) and the (single) returned value is encoded in the place of the function.
!!! note
All examples below use in-memory JSON or content read from the SPIFFS file system. However, where a streaming implementation really shines is in fetching large JSON structures from the remote resources and extracting values on-the-fly. An elaborate streaming example can be found in the [`/lua_examples`](../../../lua_examples/sjson-streaming.lua) folder.
## sjson.encoder() ## sjson.encoder()
This creates an encoder object that can convert a Lua object into a JSON encoded string. This creates an encoder object that can convert a Lua object into a JSON encoded string.
@ -53,7 +57,8 @@ A string of up to `size` bytes, or `nil` if the encoding is complete and all dat
#### Example #### Example
The following example prints out (in 64 byte chunks) a JSON encoded string containing the first 4k of every file in the file system. The total string The following example prints out (in 64 byte chunks) a JSON encoded string containing the first 4k of every file in the file system. The total string
can be bigger than the total amount of memory on the NodeMCU. can be bigger than the total amount of memory on the NodeMCU.
```
```lua
function files() function files()
result = {} result = {}
for k,v in pairs(file.list()) do for k,v in pairs(file.list()) do
@ -230,5 +235,5 @@ for k,v in pairs(t) do print(k,v) end
##Constants ##Constants
There is one constant -- `sjson.NULL` -- which is used in Lua structures to represent the presence of a JSON null. There is one constant, `sjson.NULL`, which is used in Lua structures to represent the presence of a JSON null.

View File

@ -0,0 +1,70 @@
-- Test sjson and GitHub API
local s = tls.createConnection()
s:on("connection", function(sck, c)
sck:send("GET /repos/nodemcu/nodemcu-firmware/git/trees/master HTTP/1.0\r\nUser-agent: nodemcu/0.1\r\nHost: api.github.com\r\nConnection: close\r\nAccept: application/json\r\n\r\n")
end)
function startswith(String, Start)
return string.sub(String, 1, string.len(Start)) == Start
end
local seenBlank = false
local partial
local wantval = { tree = 1, path = 1, url = 1 }
-- Make an sjson decoder that only keeps certain fields
local decoder = sjson.decoder({
metatable =
{
__newindex = function(t, k, v)
if wantval[k] or type(k) == "number" then
rawset(t, k, v)
end
end
}
})
local function handledata(s)
decoder:write(s)
end
-- The receive callback is somewhat gnarly as it has to deal with find the end of the header
-- and having the newline sequence split across packets
s:on("receive", function(sck, c)
if partial then
c = partial .. c
partial = nil
end
if seenBlank then
handledata(c)
return
end
while c do
if startswith(c, "\r\n") then
seenBlank = true
c = c:sub(3)
handledata(c)
return
end
local s, e = c:find("\r\n")
if s then
-- Throw away line
c = c:sub(e + 1)
else
partial = c
c = nil
end
end
end)
local function getresult()
local result = decoder:result()
-- This gets the resulting decoded object with only the required fields
print(result['tree'][4]['path'], "is at",
result['tree'][4]['url'])
end
s:on("disconnection", getresult)
s:on("reconnection", getresult)
-- Make it all happen!
s:connect(443, "api.github.com")