Skip to main content

jsonversation

A Python library for streaming JSON parsing that enables real-time processing of JSON data as it arrives. Perfect for handling large JSON responses, streaming APIs, or any scenario where you need to process JSON data progressively.

Installation

Coming soon!

Key Features

  • Streaming JSON Parsing: Process JSON data as it arrives, without waiting for complete payloads
  • Type-Safe Models: Define strongly-typed data structures with automatic validation
  • Real-time Callbacks: React to data changes as they happen with customizable callbacks
  • Progressive Updates: Handle partial JSON data and incremental updates seamlessly

Quick Start

Basic Usage

import jsonversation as jv


# Define your data structure
class ChatMessage(jv.Object):
    role: jv.String
    content: jv.String
    timestamp: jv.String
    token_count: jv.Atomic[int]
    is_complete: jv.Atomic[bool]


# Create a parser
message = ChatMessage()

# Process streaming JSON data
json_chunk1 = '{"role": "assistant", "content": "Hello'
json_chunk2 = ' world!", "timestamp": "2024-01-01T12:00:00Z", "token_count": 42, "is_complete": true}'

with jv.Parser(message) as parser:
    parser.push(json_chunk1)
    print(message.content.get_value())  # "Hello"

    parser.push(json_chunk2)
    print(message.content.get_value())  # "Hello world!"
    print(message.role.get_value())  # "assistant"
    print(message.token_count.get_value())  # 42
    print(message.is_complete.get_value())  # True

Real-time Callbacks

import jsonversation as jv


class StreamingResponse(jv.Object):
    message: jv.String
    tokens: jv.List[jv.String]


response = StreamingResponse()


# Set up real-time callbacks
def on_message_update(chunk: str):
    print(f"New text: {chunk}")


def on_new_token(token: jv.String):
    print(f"New token: {token.get_value()}")


def on_message_complete(full_message: str):
    print(f"Complete message: {full_message}")


response.message.on_append(on_message_update)
response.tokens.on_append(on_new_token)
response.message.on_complete(on_message_complete)

# Simulate streaming data
with jv.Parser(response) as parser:
    parser.push('{"message": "The quick')
    parser.push(' brown fox", "tokens": ["The", "quick"]}')

Working with Atomic Types

The Atomic class handles primitive types that arrive as complete values rather than streaming text:

import jsonversation as jv


class APIResponse(jv.Object):
    message: jv.String
    status_code: jv.Atomic[int]
    success: jv.Atomic[bool]
    response_time: jv.Atomic[float]


response = APIResponse()


# Set up callbacks for atomic values
def on_status_change(status: int | None):
    if status:
        print(f"Status code: {status}")
        if status >= 400:
            print("Error response detected!")


def on_completion(success: bool | None):
    if success is not None:
        print(f"Request {'succeeded' if success else 'failed'}")


response.status_code.on_complete(on_status_change)
response.success.on_complete(on_completion)

# Process JSON with atomic values
with jv.Parser(response) as parser:
    parser.push('{"message": "Request completed", "status_code": 200')
    parser.push(', "success": true, "response_time": 1.23}')
    # Callbacks will be triggered when atomic values are completed

print(response.status_code.get_value())  # 200
print(response.success.get_value())  # True
print(response.response_time.get_value())  # 1.23

Complex Nested Structures

import jsonversation as jv


class Author(jv.Object):
    name: jv.String
    email: jv.String


class Comment(jv.Object):
    id: jv.String
    text: jv.String
    author: Author


class BlogPost(jv.Object):
    title: jv.String
    content: jv.String
    author: Author
    comments: jv.List[Comment]
    tags: jv.List[jv.String]


# Create and use the parser
post = BlogPost()

# Process complex JSON
complex_json = """
{
    "title": "Streaming JSON in Python",
    "content": "This is a comprehensive guide...",
    "author": {
        "name": "Jane Doe",
        "email": "jane@example.com"
    },
    "comments": [
        {
            "id": "1",
            "text": "Great article!",
            "author": {
                "name": "John Smith",
                "email": "john@example.com"
            }
        }
    ],
    "tags": ["python", "json", "streaming"]
}
"""

with jv.Parser(post) as parser:
    parser.push(complex_json)
    # Access nested data
    print(post.title.get_value())  # "Streaming JSON in Python"
    print(post.author.name.get_value())  # "Jane Doe"
    print(post.comments.get_value()[0].text.get_value())  # "Great article!"
    print([tag.get_value for tag in post.tags.get_value()])  # ["python", "json", "streaming"]

AsyncIO

Jsonversation supports async callbacks as well. The API is very similar between the sync/async classes, with the only difference being that the async module supports async callback functions.

Example

import asyncio
import jsonversation.aio as jv


class StreamingResponse(jv.Object):
    message: jv.String
    tokens: jv.List[jv.String]


response = StreamingResponse()


# Set up real-time callbacks
async def on_message_update(chunk: str):
    await asyncio.sleep(0.001)
    print(f"New text: {chunk}")


async def on_new_token(token: jv.String):
    await asyncio.sleep(0.001)
    print(f"New token: {token.get_value()}")


async def on_message_complete(full_message: str):
    await asyncio.sleep(0.001)
    print(f"Complete message: {full_message}")


response.message.on_append(on_message_update)
response.tokens.on_append(on_new_token)
response.message.on_complete(on_message_complete)


async def run():
    async with jv.Parser(response) as parser:
        await parser.push('{"message": "The quick')
        await parser.push(' brown fox", "tokens": ["The", "quick"]}')


asyncio.run(run())

API Reference

Core Classes

  1. Parser(obj: Object)

    Main parser class for processing streaming JSON data.

    Methods:

    • push(chunk: str) - Process a chunk of JSON data
  2. Object

    Base class for defining structured data models.

    Methods:

    • update(value: dict) - Update object with dictionary data
  3. String

    String field type with streaming capabilities.

    Properties:

    • value - Get current string value

    Methods:

    • on_append(callback) - Register callback for new text chunks
    • on_complete(callback) - Register callback for completion
    • update(value: str) - Update with new string value
  4. List[T]

    List field type for collections of items.

    Properties:

    • value - Get current list of items

    Methods:

    • on_append(callback) - Register callback for new items
    • on_complete(callback) - Register callback for completion
    • update(value: list) - Update with new list data

Requirements

  • Python 3.9+
  • jiter (for JSON parsing)

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Metadata

Release files for jsonversation 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jsonversation 0.1.3
File Size Uploaded
jsonversation-0.1.3.tar.gz 8.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jsonversation 0.1.3
File Interpreter ABI Platform
jsonversation-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 18.5 kB

Release files / jsonversation-0.1.3.tar.gz

Download URL jsonversation-0.1.3.tar.gz
Size 8.9 kB
Tags Source
SHA-256 checksum
How to use checksums
735db7528f0e2a3887e02ee97c356fd63b12df2371c82a45ef25826b759e26fa
BLAKE2b-256 checksum
How to use checksums
f0796e861247710152893b48f77d4fe47bc3ac0e5e155afba042483e2a44c502
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2025.

Transparency log

Release files / jsonversation-0.1.3-py3-none-any.whl

Download URL jsonversation-0.1.3-py3-none-any.whl
Size 9.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b7d9e86c6b5e6843e5d154e4f35300e6ef5e6c7b377ea949d12a9a42b742ac8d
BLAKE2b-256 checksum
How to use checksums
98e6237f9fede11cd1b636a180f5985b2497d5a51701ac1d4cd35b6299ed4291
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page