Skip to content

Configurable pretty-printing #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@ print(json.encode({ 1, 2, 'fred', {first='mars',second='venus',third='earth'} })
```json
[1,2,"fred", {"first":"mars","second":"venus","third","earth"}]
```
Order of object keys is not guaranteed.

```lua
json = require('json')
print(json.encode(
{ 1, 2, 'fred', {first='mars',second='venus',third='earth'} },
{ sort_keys=true, pretty=true, indent=4 }))
```
```json
[
1,
2,
"fred",
{
"first": "mars",
"second": "venus",
"third": "earth"
}
]
```

## Decoding ##

Expand Down
7 changes: 7 additions & 0 deletions examples/tests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ function testJSON4Lua()
-- NB: This test can fail because of order: need to test further once
-- decoding is supported.
-- assert(r==[[{"age":35,"Name":"Craig","email":"craig@lateral.co.za"}]])
r = json.encode(s, {sort_keys=true})
assert(r==[[{"Name":"Craig","age":35,"email":"craig@lateral.co.za"}]], r)

-- Test pretty-printing
s = { 2, 'joe', false, nil, 'hi' }
r = json.encode(s, { pretty=true, indent=2 })
assert(r=='[\n 2,\n "joe",\n false,\n null,\n "hi"\n]', r)

-- Test decode_scanWhitespace
if nil then
Expand Down
4 changes: 2 additions & 2 deletions examples/timetrials.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
]]--


require('json')
json = require('json')
require('os')
require('table')

Expand Down Expand Up @@ -43,4 +43,4 @@ print (jstr)
--print(type(t1))
local t2 = os.clock()

print ("Elapsed time=" .. os.difftime(t2,t1) .. "s")
print ("Elapsed time=" .. (t2 - t1) .. "s")
89 changes: 80 additions & 9 deletions json/json.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
--
-- USAGE:
-- This module exposes two functions:
-- json.encode(o)
-- json.encode(o, options)
-- Returns the table / string / boolean / number / nil / json.null value as a JSON-encoded string.
-- options is an optional table giving additional options:
-- sort_keys - sort object keys alphabetically
-- pretty - put spaces after ':' and ',',
-- indent - optional indent amount for pretty-printing
-- json.decode(json_string)
-- Returns a Lua object populated with the data encoded in the JSON string json_string.
--
Expand Down Expand Up @@ -52,14 +56,20 @@ local decode_scanWhitespace
local encodeString
local isArray
local isEncodable
local __genOrderedIndex
local orderedNext
local orderedPairs

-----------------------------------------------------------------------------
-- PUBLIC FUNCTIONS
-----------------------------------------------------------------------------
--- Encodes an arbitrary Lua object / variable.
-- @param v The Lua object / variable to be JSON encoded.
-- @return String containing the JSON encoding in internal Lua string format (i.e. not unicode)
function json.encode (v)
function json.encode (v, options, depth)
options = options or {}
depth = depth or 0

-- Handle nil values
if v==nil then
return "null"
Expand All @@ -80,23 +90,34 @@ function json.encode (v)
-- Handle tables
if vtype=='table' then
local rval = {}
local indent = options.indent and ('\n' .. string.rep(' ', options.indent * (depth + 1))) or ''
-- Consider arrays separately
local bArray, maxCount = isArray(v)
if bArray then
for i = 1,maxCount do
table.insert(rval, json.encode(v[i]))
table.insert(rval, json.encode(v[i], options, depth + 1))
end
else -- An object, not an array
for i,j in pairs(v) do
local iter = options.sort_keys and orderedPairs or pairs
local colon = options.pretty and '": ' or '":'
for i,j in iter(v) do
if isEncodable(i) and isEncodable(j) then
table.insert(rval, '"' .. json_private.encodeString(i) .. '":' .. json.encode(j))
table.insert(rval, '"' .. json_private.encodeString(i) .. colon .. json.encode(j, options, depth + 1))
end
end
end
if bArray then
return '[' .. table.concat(rval,',') ..']'

local brackets = bArray and {'[',']'} or {'{','}'}
if options.indent then
local indent = string.rep(' ', options.indent)
return table.concat({
brackets[1],
indent:rep(depth+1) .. table.concat(rval, ',\n' .. indent:rep(depth+1)),
indent:rep(depth) .. brackets[2]
}, '\n')
else
return '{' .. table.concat(rval,',') .. '}'
local comma = options.pretty and ', ' or ','
return brackets[1] .. table.concat(rval, comma) .. brackets[2]
end
end

Expand Down Expand Up @@ -414,4 +435,54 @@ function isEncodable(o)
return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or (t=='function' and o==null)
end

return json
--[[
Ordered table iterator, allow to iterate on the natural order of the keys of a
table.

Source: http://lua-users.org/wiki/SortedIteration
]]
function __genOrderedIndex( t )
local orderedIndex = {}
for key in pairs(t) do
table.insert( orderedIndex, key )
end
table.sort( orderedIndex )
return orderedIndex
end

function orderedNext(t, state)
-- Equivalent of the next function, but returns the keys in the alphabetic
-- order. We use a temporary ordered key table that is stored in the
-- table being iterated.

--print("orderedNext: state = "..tostring(state) )
if state == nil then
-- the first time, generate the index
t.__orderedIndex = __genOrderedIndex( t )
key = t.__orderedIndex[1]
return key, t[key]
end
-- fetch the next value
key = nil
for i = 1,table.getn(t.__orderedIndex) do
if t.__orderedIndex[i] == state then
key = t.__orderedIndex[i+1]
end
end

if key then
return key, t[key]
end

-- no more value to return, cleanup
t.__orderedIndex = nil
return
end

function orderedPairs(t)
-- Equivalent of the pairs() function on tables. Allows to iterate
-- in order
return orderedNext, t, nil
end

return json