Skip to main content

A flexible JSON parser

Project description

fJson

English | 中文

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 value style 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, supports indent, multi_line, ascii_only parameters
  • from_json(cls, json_str: str) -> Any: Parse object from JSON string
  • dict(self) -> dict: Convert object to dictionary
  • from_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}")

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simple_fjson-0.1.3.tar.gz (15.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simple_fjson-0.1.3-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file simple_fjson-0.1.3.tar.gz.

File metadata

  • Download URL: simple_fjson-0.1.3.tar.gz
  • Upload date:
  • Size: 15.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.9

File hashes

Hashes for simple_fjson-0.1.3.tar.gz
Algorithm Hash digest
SHA256 83879726c0afaff730b25fc4cdf43ad980ee70f343dc68592ffabe57792719b0
MD5 bce304eeb627f569ac7eef7072b91ff8
BLAKE2b-256 490c2d4c4bfa5819b3d8be4f2190149115824dfd07820f6833698ea9ee2af765

See more details on using hashes here.

File details

Details for the file simple_fjson-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: simple_fjson-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.9

File hashes

Hashes for simple_fjson-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 59b6903b2ee9f77c8a8a9d4de0a3f88e9f5acb9b8898e1f4a230b88e088364bb
MD5 4c737df19829e067690147b712119eb1
BLAKE2b-256 944875ae528e0c2ac3aa037f9fb2432e99f91d247c9c5e1c9a5e7822c8fdfb52

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page