An easy-to-use JSON parsing and manipulation library for the Ring programming language
Built on Glaze - A high-performance C++ JSON library
- β‘ High Performance: Built on the blazing-fast Glaze C++ library
- π Cross-Platform: Windows, Linux, macOS, and FreeBSD
- π Parse & Generate: Encode/decode JSON with pretty print support
- π§ Manipulation: Merge, query, validate, compare JSON documents
- π Format Conversion: CSV, TOML, BEVE, CBOR, NDJSON, Base64
- π RFC Support: JSON Pointer, JSON Patch, JSON Merge Patch
- π¬ JSONC: Parse JSON with comments
- Ring Language: Ensure you have Ring version 1.25 or higher installed. You can download it from the official Ring website.
The recommended way to install Ring SimpleJSON is through the Ring Package Manager (RingPM).
ringpm install simplejson from ysdragonFirst, load the library in your Ring script:
load "simplejson.ring"Convert JSON strings into Ring lists:
jsonString = '{"name": "Ring", "version": 1.25, "features": ["fast", "simple", "flexible"]}'
data = json_decode(jsonString)
# Access data using Ring list syntax
? data[:name] # Output: Ring
? data[:version] # Output: 1.25
? data[:features][1] # Output: fastConvert Ring lists into JSON strings:
# Create a Ring list structure
myData = [
["name", "Ring Language"],
["version", 1.25],
["features", ["fast", "simple", "flexible"]],
["active", 1]
]
# Convert to JSON string
jsonString = json_encode(myData)
? jsonString
# Output: {"active":1,"features":["fast","simple","flexible"],"name":"Ring Language","version":1.25}
# Pretty-print with indentation (optional second parameter)
prettyJson = json_encode(myData, 1)
? prettyJson# Nested structure
userProfile = [
["user", [
["name", "John Doe"],
["age", 30],
["email", "john@example.com"]
]],
["preferences", [
["theme", "dark"],
["notifications", 1]
]],
["posts", [
["title", "Hello World", "content", "First post"],
["title", "JSON in Ring", "content", "Using SimpleJSON library"]
]]
]
# Encode to JSON
jsonData = json_encode(userProfile, 1)
? jsonData
# Decode back to Ring structure
decodedData = json_decode(jsonData)
? decodedData[:user][:name] # Output: John DoeParses a JSON string into a Ring list structure.
- Parameters:
jsonString(string): The JSON string to parse
- Returns: A Ring list containing the parsed data
Converts a Ring list structure into a JSON string.
- Parameters:
ringList: The Ring list to convertprettyPrint(optional): Pass1/TRUEto format JSON with indentation,0/FALSEor omit for compact format
- Returns: A JSON string representation of the list data
Returns the version of the underlying Glaze library.
- Parameters: None
- Returns: A string representing the Glaze library version
Validates whether a string is valid JSON.
- Parameters:
jsonString(string): The string to validate
- Returns:
1if valid JSON,0if invalid
? json_valid('{"name": "John"}') # Output: 1
? json_valid('{invalid}') # Output: 0Returns the type of the root JSON value.
- Parameters:
jsonString(string): A valid JSON string
- Returns: One of:
"object","array","string","number","boolean","null", or"invalid"
? json_type('{"a": 1}') # Output: object
? json_type('[1, 2, 3]') # Output: array
? json_type('"hello"') # Output: string
? json_type('42') # Output: number
? json_type('true') # Output: boolean
? json_type('null') # Output: nullReturns a list of all keys in a JSON object.
- Parameters:
jsonString(string): A JSON object string
- Returns: A Ring list containing all keys
keys = json_keys('{"name": "John", "age": 30, "city": "NYC"}')
for key in keys
? key
next
# Output: age, city, name (order may vary)Checks if a key exists in a JSON object.
- Parameters:
jsonString(string): A JSON object stringkey(string): The key to check for
- Returns:
1if key exists,0otherwise
json = '{"name": "John", "age": 30}'
? json_has(json, "name") # Output: 1
? json_has(json, "email") # Output: 0Merges two JSON objects. Keys from the second object overwrite keys from the first.
- Parameters:
jsonObject1(string): The base JSON objectjsonObject2(string): The JSON object to merge in
- Returns: A merged JSON object string
obj1 = '{"a": 1, "b": 2}'
obj2 = '{"b": 3, "c": 4}'
? json_merge(obj1, obj2) # Output: {"a":1,"b":3,"c":4}Access nested values using JSON Pointer syntax (RFC 6901).
- Parameters:
jsonString(string): A valid JSON stringpointer(string): A JSON Pointer path (e.g.,/user/nameor/items/0)
- Returns: The value at the specified path (string, number, or list)
json = '{"user": {"name": "John", "address": {"city": "NYC"}}, "items": [1, 2, 3]}'
? json_pointer(json, "/user/name") # Output: John
? json_pointer(json, "/user/address/city") # Output: NYC
? json_pointer(json, "/items/0") # Output: 1Removes all unnecessary whitespace from a JSON string.
- Parameters:
jsonString(string): A JSON string (can be pretty-printed)
- Returns: A compact JSON string with no extra whitespace
pretty = '{
"name": "John",
"age": 30
}'
? json_minify(pretty) # Output: {"name":"John","age":30}Formats a JSON string with indentation for readability.
- Parameters:
jsonString(string): A compact JSON string
- Returns: A pretty-printed JSON string with 3-space indentation
compact = '{"name":"John","age":30}'
? json_prettify(compact)
# Output:
# {
# "name": "John",
# "age": 30
# }Reads and parses a JSON file.
- Parameters:
filePath(string): Path to the JSON file
- Returns: A Ring list containing the parsed data
data = json_read_file("config.json")
? data[:setting]Writes a Ring list to a JSON file.
- Parameters:
ringList: The Ring list to writefilePath(string): Path to the output fileprettyPrint(optional): Pass1for formatted output
- Returns:
1on success
config = [["name", "MyApp"], ["version", "1.0"]]
json_write_file(config, "config.json", 1)Converts a JSON string to BEVE (Binary Efficient Versatile Encoding) format.
- Parameters:
jsonString(string): A valid JSON string
- Returns: Binary BEVE data as a string
json = '{"test": 123, "hello": "world"}'
beve = json_to_beve(json)
? len(beve) # Binary data is typically smallerConverts BEVE binary data back to a JSON string.
- Parameters:
beveData(string): BEVE binary data
- Returns: A JSON string
json = '{"test": 123}'
beve = json_to_beve(json)
restored = beve_to_json(beve)
? restored # Output: {"hello":"world","test":123}Applies RFC 6902 JSON Patch operations to a document.
- Parameters:
documentJson(string): The target JSON documentoperationsJson(string): A JSON array of patch operations
- Returns: The patched JSON document string
Supported operations: add, remove, replace, move, copy, test
doc = '{"name": "John", "age": 30}'
ops = '[{"op": "replace", "path": "/name", "value": "Jane"}, {"op": "add", "path": "/city", "value": "NYC"}]'
result = json_patch(doc, ops)
? result # Output: {"age":30,"city":"NYC","name":"Jane"}
# Add to array
doc2 = '{"items": [1, 2, 3]}'
ops2 = '[{"op": "add", "path": "/items/-", "value": 4}]'
? json_patch(doc2, ops2) # Output: {"items":[1,2,3,4]}Generates an RFC 6902 JSON Patch that transforms the source into the target.
- Parameters:
sourceJson(string): The original JSON documenttargetJson(string): The target JSON document
- Returns: A JSON array of patch operations
source = '{"name": "John", "age": 30}'
target = '{"name": "Jane", "age": 30, "city": "NYC"}'
patch = json_diff(source, target)
? patch # Output: [{"op":"add","path":"/city","value":"NYC"},{"op":"replace","path":"/name","value":"Jane"}]
# Apply the patch to get back to target
? json_patch(source, patch) # Same as targetApplies an RFC 7386 JSON Merge Patch to a document. Simpler than JSON Patch but less powerful.
- Parameters:
targetJson(string): The target JSON documentpatchJson(string): The merge patch object (null values remove keys)
- Returns: The patched JSON document string
target = '{"a": "b", "c": {"d": "e", "f": "g"}}'
patch = '{"a": "z", "c": {"f": null}}'
result = json_merge_patch(target, patch)
? result # Output: {"a":"z","c":{"d":"e"}} (f was removed by null)
# Simple update
doc = '{"name": "John"}'
update = '{"age": 30, "city": "NYC"}'
? json_merge_patch(doc, update) # Output: {"age":30,"city":"NYC","name":"John"}Generates an RFC 7386 Merge Patch that transforms source into target.
- Parameters:
sourceJson(string): The original JSON documenttargetJson(string): The target JSON document
- Returns: A merge patch object
source = '{"a": "b", "c": "d"}'
target = '{"a": "b", "c": "e", "f": "g"}'
patch = json_merge_diff(source, target)
? patch # Output: {"c":"e","f":"g"}Converts a JSON string to CBOR (Concise Binary Object Representation) format.
- Parameters:
jsonString(string): A valid JSON string
- Returns: Binary CBOR data as a string
json = '{"test": 123, "hello": "world"}'
cbor = json_to_cbor(json)
? len(cbor) # Binary data lengthConverts CBOR binary data back to a JSON string.
- Parameters:
cborData(string): CBOR binary data
- Returns: A JSON string
json = '{"test": 123, "array": [1, 2, 3]}'
cbor = json_to_cbor(json)
restored = cbor_to_json(cbor)
? restored # Output: {"array":[1,2,3],"test":123}Encodes a Ring list of data structures as NDJSON (Newline Delimited JSON / JSON Lines).
- Parameters:
ringList: A Ring list where each item is a data structure to encode
- Returns: An NDJSON string (one JSON object per line)
records = [
[["id", 1], ["name", "Alice"]],
[["id", 2], ["name", "Bob"]],
[["id", 3], ["name", "Charlie"]]
]
ndjson = json_ndjson_encode(records)
? ndjson
# Output:
# {"id":1,"name":"Alice"}
# {"id":2,"name":"Bob"}
# {"id":3,"name":"Charlie"}Decodes an NDJSON string into a Ring list of data structures.
- Parameters:
ndjsonString(string): An NDJSON string (one JSON object per line)
- Returns: A Ring list where each item is a decoded JSON object
ndjson = '{"a": 1}
{"b": 2}
{"c": 3}'
records = json_ndjson_decode(ndjson)
? len(records) # Output: 3
for record in records
? json_encode(record)
next
# Output:
# {"a":1}
# {"b":2}
# {"c":3}Compares two JSON documents for semantic equality (ignoring key order).
- Parameters:
jsonString1(string): First JSON documentjsonString2(string): Second JSON document
- Returns:
1if equal,0if not equal
? json_equal('{"a":1,"b":2}', '{"b":2,"a":1}') # Output: 1 (same content)
? json_equal('{"a":1}', '{"a":2}') # Output: 0 (different values)
? json_equal('[1,2,3]', '[1,2,3]') # Output: 1 (same array)Returns the number of elements in a JSON object or array.
- Parameters:
jsonString(string): A JSON object or array
- Returns: Number of keys (for objects) or elements (for arrays)
? json_size('{"a":1,"b":2,"c":3}') # Output: 3
? json_size('[1,2,3,4,5]') # Output: 5
? json_size('{}') # Output: 0Returns the maximum nesting depth of a JSON document.
- Parameters:
jsonString(string): A valid JSON string
- Returns: The maximum nesting depth (0 for scalars)
? json_depth('{"a":1}') # Output: 1
? json_depth('{"a":{"b":1}}') # Output: 2
? json_depth('{"a":{"b":{"c":1}}}') # Output: 3Sorts all object keys alphabetically (recursively).
- Parameters:
jsonString(string): A valid JSON string
- Returns: JSON string with sorted keys
? json_sort_keys('{"z":1,"a":2,"m":3}') # Output: {"a":2,"m":3,"z":1}Queries a JSON document using a path (similar to JSON Pointer).
- Parameters:
jsonString(string): A valid JSON stringpath(string): Path to query (e.g.,/users/0/name)
- Returns: JSON string of the value at path, or
"null"if not found
json = '{"users":[{"name":"Alice"},{"name":"Bob"}]}'
? json_query(json, "/users/0/name") # Output: "Alice"
? json_query(json, "/missing") # Output: nullParses JSON with comments (JSONC) and returns standard JSON.
- Parameters:
jsoncString(string): JSON string with//or/* */comments
- Returns: Standard JSON string with comments removed
jsonc = '{
// This is a comment
"name": "test",
/* Multi-line
comment */
"value": 123
}'
? json_strip_comments(jsonc) # Output: {"name":"test","value":123}Encodes a string to Base64.
- Parameters:
data(string): The data to encode
- Returns: Base64 encoded string
? base64_encode("Hello, World!") # Output: SGVsbG8sIFdvcmxkIQ==Decodes a Base64 string.
- Parameters:
encodedString(string): Base64 encoded string
- Returns: Decoded data
? base64_decode("SGVsbG8sIFdvcmxkIQ==") # Output: Hello, World!Converts a CSV string to a JSON array of objects.
- Parameters:
csvString(string): CSV data with header row
- Returns: JSON array where each row is an object
csv = "name,age,city
Alice,30,NYC
Bob,25,LA"
? csv_to_json(csv)
# Output: [{"age":30,"city":"NYC","name":"Alice"},{"age":25,"city":"LA","name":"Bob"}]Converts a JSON array of objects to CSV format.
- Parameters:
jsonString(string): JSON array of objects
- Returns: CSV string with header row
json = '[{"name":"Alice","age":30},{"name":"Bob","age":25}]'
? json_to_csv(json)
# Output:
# age,name
# 30,Alice
# 25,BobConverts a TOML string to JSON.
- Parameters:
tomlString(string): TOML formatted data
- Returns: JSON string
toml = 'title = "Example"
[database]
host = "localhost"
port = 5432'
? toml_to_json(toml)
# Output: {"database":{"host":"localhost","port":5432},"title":"Example"}Converts a JSON string to TOML format.
- Parameters:
jsonString(string): A valid JSON object
- Returns: TOML formatted string
json = '{"name":"MyApp","port":8080}'
? json_to_toml(json)
# Output:
# name = "MyApp"
# port = 8080If you wish to contribute to the development of Ring SimpleJSON or build it from the source, follow these steps.
- CMake: Version 3.16 or higher.
- C++23 Compiler: A C++ compiler with C++23 support (GCC 13+, Clang 18+, MSVC 2022).
- Ring Source Code: You will need to have the Ring language source code available on your machine.
-
Clone the Repository:
git clone https://github.com/ysdragon/simplejson.git --recursive
Note: If you installed the library via RingPM, you can skip this step.
-
Set the
RINGEnvironment Variable: This variable must point to the root directory of the Ring language source code.- Windows (Command Prompt):
set RING=X:\path\to\ring
- Windows (PowerShell):
$env:RING = "X:\path\to\ring"
- Unix-like Systems (Linux, macOS or FreeBSD):
export RING=/path/to/ring
- Windows (Command Prompt):
-
Configure with CMake: Create a build directory and run CMake from within it.
mkdir build cd build cmake .. -
Build the Project: Compile the source code using the build toolchain configured by CMake.
cmake --build .The compiled library will be available in the
lib/<os>/<arch>directory.
Contributions are always welcome! If you have suggestions for improvements or have identified a bug, please feel free to open an issue or submit a pull request.
This project is licensed under the MIT License. See the LICENSE file for more details.