fJson
fJson is a lenient JSON parser that supports comments, unquoted keys, arrays, tuples, and more. While it doesn't support special character escaping, it does support multi-line strings, multi-line comments, and fullwidth quotes.
Initially created to handle LLM output parsing issues, it later evolved to support additional use cases like command-line argument parsing.
This project is primarily Python-focused, leveraging Python's dynamic typing for direct parsing. Languages like C++ would require custom data structure implementations.
Features
- Dictionaries: Support for unquoted keys
- Lists: Support for standard JSON list format
- Tuples: Support for tuple format
- Parameter Groups: Support for
--key valuestyle parameter groups - Multi-line Strings: Support for
R"delimiter(content)delimiter"style multi-line strings - Base64 Encoded Strings: Support for
$"base64string"style Base64 encoded strings - Expression Evaluation: Support for various expressions like Cartesian products, string concatenation, conditional expressions, etc.
- More features planned
Usage
All classes except the decode function are used internally for JSON parsing. The decode function serves as the public interface, taking a string input and returning a parsed object.
Example
from fjson import decode
text = '''
{
key1: value1,
key2: {
key3: value3,
key4: value4
},
key5: [value5, value6, value7],
key6: (value8, value9),
key7: (--key10 value10 --key11 value11),
key8: R"delimiter(
multi-line
string
)delimiter",
key9: $"YmFzZTY0IGVuY29kZWQgc3RyaW5n"
}
'''
result = decode(text)
print(result)
Functions
decode(json_str: str) -> Any
Parse a JSON string and return the parsed object.
def decode(json_str):
"""
Parse a JSON string
"""
tokens = fJsonLexer().tokenize(json_str)
tokens = fJsonLexer().reject_comments(tokens)
tokens = fJsonLexer().concat_negative_number(tokens)
return fJsonBuilder(tokens).build()
encode(obj: Any, indent: int = None, multi_line: bool = False, ascii_only: bool = False) -> str
Encode an object into a JSON string.
Decorators
@DataClass
Declare a data class with direct fJson serialization support, automatically adding the following methods:
json(self, **kwargs) -> str: Encode object to JSON string, supportsindent,multi_line,ascii_onlyparametersfrom_json(cls, json_str: str) -> Any: Parse object from JSON stringdict(self) -> dict: Convert object to dictionaryfrom_dict(cls, data: dict) -> Any: Parse object from dictionary
Examples
import fJson as json
fjson_str = """
/* This is a comment */
[
{
name: 'John',
age: 30,
city: "New York",
male: true
}, // dictionary
{
"name": "Ja" + "ne",
'age': 5 * 5,
"city": "London",
male: fAlsE
}
], // list
{A,B,C} * {1,2,3}, // Cartesian product
(1, 2), // tuple
{1, 2, 3}, // set
--draw circle --rotate 90 --fill red --position (0,0) (1,1) (2,2), // parameter group
R"delimiter(
multi-line
string
)delimiter", // multi-line string
$"YmFzZTY0IGVuY29kZWQgYmFzZTY0IGVuY29kZWQ=", // Base64 encoded string
[1, 2, 3] + [4, 5, 6], // concatenation expression
[1, 2] * [3, 4], // element-wise multiplication
[1 ,2] * 3 // list multiplication
"""
print(json.decode(fjson_str))
@json.DataClass
class Person:
def __init__(self, name: str, age: int, hobbies: list = None, pair: tuple = (), bytestr: bytes = b''):
self.name = name
self.age = age
self.hobbies = hobbies or []
self.pair = pair
self.bytestr = bytestr
# Create object
person = Person(name="John", age=25, hobbies=["reading", "running"], pair=(1, ), bytestr=b'base64 encoded base64 encoded')
# Convert to JSON
json_str = person.json(indent = 4, multi_line = True, ascii_only = True)
print("Convert to JSON:")
print(json_str)
# Create new object from JSON
new_person = Person.load_json(json_str)
print("\nRestore from JSON:")
print(f"Name: {new_person.name}")
print(f"Age: {new_person.age}")
print(f"Hobbies: {new_person.hobbies}")
print(f"Tuple: {new_person.pair}")
print(f"Bytes: {new_person.bytestr}")
# Convert to dictionary
person_dict = person.dict()
print("\nConvert to dictionary:")
print(person_dict)
# Create new object from dictionary
dict_person = Person.load_dict(person_dict)
print("\nRestore from dictionary:")
print(f"Name: {dict_person.name}")
print(f"Age: {dict_person.age}")
print(f"Hobbies: {dict_person.hobbies}")
print(f"Tuple: {dict_person.pair}")
print(f"Bytes: {dict_person.bytestr}")
Metadata
Release files for simple-fjson 0.1.4.post2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| simple_fjson-0.1.4.post2.tar.gz | 16.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| simple_fjson-0.1.4.post2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 29.3 kB
Release files / simple_fjson-0.1.4.post2.tar.gz
| Download URL | simple_fjson-0.1.4.post2.tar.gz |
|---|---|
| Size | 16.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
77b5c56f691d7f3b0460baa724348059ad795873b1f6e986f235bcbc323005e4
|
|
BLAKE2b-256 checksum How to use checksums |
588777d5a66001197d47c77f82352513da44d935e0c226983f2774aeb2e8addf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.10.9
|
Release files / simple_fjson-0.1.4.post2-py3-none-any.whl
| Download URL | simple_fjson-0.1.4.post2-py3-none-any.whl |
|---|---|
| Size | 13.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
70c2e28a9d69bfc9357978fa6e6c24e8bdfa4f742dcbb79cac9ee00a24d8c685
|
|
BLAKE2b-256 checksum How to use checksums |
af386d083f449141a9d3c809050a1155c5712ebc13028c7dddaa3ddf7fadd22e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.10.9
|