CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-flask

A simple framework for building complex web applications.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

json-support.mddocs/

JSON Support

Flask provides comprehensive JSON handling capabilities through the flask.json module, including serialization, deserialization, and response creation with Flask-specific enhancements.

Capabilities

JSON Response Creation

Function for creating JSON responses with proper headers and formatting.

def jsonify(*args, **kwargs) -> Response:
    """
    Create a JSON response from arguments.
    
    Args:
        *args: Positional arguments (single value or multiple values as array)
        **kwargs: Keyword arguments (treated as object properties)
        
    Returns:
        Response object with JSON content and application/json mimetype
        
    Examples:
        jsonify(message="Hello")
        jsonify([1, 2, 3])
        jsonify({"key": "value"})
        jsonify(users=[{"name": "John"}, {"name": "Jane"}])
    """

JSON Serialization

Functions for converting Python objects to JSON strings.

def dumps(obj: Any, **kwargs) -> str:
    """
    Serialize object to JSON string.
    
    Args:
        obj: Object to serialize
        **kwargs: Arguments passed to JSON encoder
        
    Returns:
        JSON string
        
    Note:
        Uses current app's JSON provider if available, otherwise standard json.dumps
    """

def dump(obj: Any, fp: IO[str], **kwargs) -> None:
    """
    Serialize object to JSON and write to file.
    
    Args:
        obj: Object to serialize
        fp: File-like object to write to
        **kwargs: Arguments passed to JSON encoder
        
    Note:
        Uses current app's JSON provider if available, otherwise standard json.dump
    """

JSON Deserialization

Functions for parsing JSON strings into Python objects.

def loads(s: str | bytes, **kwargs) -> Any:
    """
    Deserialize JSON string to Python object.
    
    Args:
        s: JSON string or bytes
        **kwargs: Arguments passed to JSON decoder
        
    Returns:
        Deserialized Python object
        
    Note:
        Uses current app's JSON provider if available, otherwise standard json.loads
    """

def load(fp: IO[AnyStr], **kwargs) -> Any:
    """
    Deserialize JSON from file to Python object.
    
    Args:
        fp: File-like object to read from
        **kwargs: Arguments passed to JSON decoder
        
    Returns:
        Deserialized Python object
        
    Note:
        Uses current app's JSON provider if available, otherwise standard json.load
    """

JSON Provider System

Classes for customizing JSON behavior in Flask applications.

class JSONProvider:
    """Base class for JSON providers."""
    
    def dumps(self, obj: Any, **kwargs) -> str:
        """Serialize object to JSON string."""
    
    def loads(self, s: str | bytes, **kwargs) -> Any:
        """Deserialize JSON string to object."""
    
    def dump(self, obj: Any, fp: IO[str], **kwargs) -> None:
        """Serialize object to JSON file."""
    
    def load(self, fp: IO[AnyStr], **kwargs) -> Any:
        """Deserialize JSON from file."""
    
    def response(self, *args, **kwargs) -> Response:
        """Create JSON response."""

class DefaultJSONProvider(JSONProvider):
    """Default JSON provider with Flask-specific enhancements."""
    
    def __init__(self, app: Flask) -> None:
        """Initialize provider for Flask app."""
    
    default: Callable[[Any], Any] | None  # Default function for non-serializable objects
    ensure_ascii: bool  # Ensure ASCII output
    sort_keys: bool  # Sort object keys
    compact: bool | None  # Compact output format
    mimetype: str  # Response mimetype

JSON Tag System

Classes for handling complex object serialization with tags.

class JSONTag:
    """Base class for JSON object tags."""
    
    key: str  # Tag key identifier
    
    def check(self, value: Any) -> bool:
        """Check if value should use this tag."""
    
    def to_json(self, value: Any) -> Any:
        """Convert value to JSON-serializable form."""
    
    def to_python(self, value: Any) -> Any:
        """Convert JSON value back to Python object."""

class TaggedJSONSerializer:
    """Serializer that handles tagged objects."""
    
    def __init__(self) -> None:
        """Initialize serializer."""
    
    def register(self, tag_class: type[JSONTag], force: bool = False, index: int | None = None) -> None:
        """Register a tag class."""
    
    def tag(self, value: Any) -> dict[str, Any]:
        """Tag a value for serialization."""
    
    def untag(self, value: dict[str, Any]) -> Any:
        """Untag a value during deserialization."""
    
    def dumps(self, value: Any, **kwargs) -> str:
        """Serialize with tagging."""
    
    def loads(self, value: str, **kwargs) -> Any:
        """Deserialize with untagging."""

Usage Examples

Basic JSON Responses

from flask import Flask, jsonify, request

app = Flask(__name__)

@app.route('/api/user/<int:user_id>')
def get_user(user_id):
    # Simple JSON response
    user = {
        'id': user_id,
        'name': f'User {user_id}',
        'email': f'user{user_id}@example.com'
    }
    return jsonify(user)

@app.route('/api/users')
def get_users():
    # JSON array response
    users = [
        {'id': 1, 'name': 'John'},
        {'id': 2, 'name': 'Jane'},
        {'id': 3, 'name': 'Bob'}
    ]
    return jsonify(users)

@app.route('/api/status')
def status():
    # JSON with multiple keys
    return jsonify(
        status='ok',
        version='1.0',
        timestamp='2023-01-01T00:00:00Z'
    )

@app.route('/api/message')
def message():
    # Simple message
    return jsonify(message='Hello, World!')

JSON Request Handling

from flask import Flask, request, jsonify
import json

app = Flask(__name__)

@app.route('/api/users', methods=['POST'])
def create_user():
    # Get JSON data from request
    if not request.is_json:
        return jsonify(error='Content-Type must be application/json'), 400
    
    data = request.get_json()
    
    # Validate required fields
    required_fields = ['name', 'email']
    for field in required_fields:
        if field not in data:
            return jsonify(error=f'Missing field: {field}'), 400
    
    # Create user (simulate)
    user = {
        'id': 123,
        'name': data['name'],
        'email': data['email'],
        'created': '2023-01-01T00:00:00Z'
    }
    
    return jsonify(user), 201

@app.route('/api/bulk-upload', methods=['POST'])
def bulk_upload():
    try:
        data = request.get_json(force=True)
    except Exception as e:
        return jsonify(error='Invalid JSON'), 400
    
    if not isinstance(data, list):
        return jsonify(error='Expected JSON array'), 400
    
    results = []
    for item in data:
        # Process each item
        results.append({
            'id': item.get('id'),
            'status': 'processed'
        })
    
    return jsonify(results=results, count=len(results))

Custom JSON Serialization

from flask import Flask, jsonify
from datetime import datetime, date
from decimal import Decimal
import uuid

app = Flask(__name__)

# Custom JSON encoder for special types
def custom_json_default(obj):
    """Custom JSON serialization for unsupported types."""
    if isinstance(obj, datetime):
        return obj.isoformat()
    elif isinstance(obj, date):
        return obj.isoformat()
    elif isinstance(obj, Decimal):
        return float(obj)
    elif isinstance(obj, uuid.UUID):
        return str(obj)
    elif hasattr(obj, 'to_dict'):
        return obj.to_dict()
    
    raise TypeError(f'Object of type {type(obj)} is not JSON serializable')

# Configure the app's JSON provider
app.json.default = custom_json_default

class User:
    def __init__(self, id, name, created):
        self.id = id
        self.name = name
        self.created = created
    
    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            'created': self.created
        }

@app.route('/api/advanced')
def advanced_json():
    data = {
        'timestamp': datetime.now(),
        'date': date.today(),
        'price': Decimal('19.99'),
        'uuid': uuid.uuid4(),
        'user': User(1, 'John', datetime.now())
    }
    
    return jsonify(data)

JSON Configuration

from flask import Flask, jsonify

app = Flask(__name__)

# Configure JSON behavior
app.json.ensure_ascii = False  # Allow Unicode characters
app.json.sort_keys = True      # Sort object keys
app.json.compact = True        # Use compact representation

@app.route('/api/unicode')
def unicode_response():
    return jsonify(
        message='Hello, 世界! 🌍',
        emoji='🚀',
        chinese='你好'
    )

@app.route('/api/pretty')
def pretty_json():
    # Override compact setting for this response
    data = {
        'users': [
            {'name': 'Alice', 'age': 30},
            {'name': 'Bob', 'age': 25}
        ],
        'meta': {
            'total': 2,
            'page': 1
        }
    }
    
    # Create pretty-printed JSON
    import json
    pretty_json = json.dumps(data, indent=2, sort_keys=True)
    
    from flask import Response
    return Response(
        pretty_json,
        mimetype='application/json'
    )

Error Handling with JSON

from flask import Flask, jsonify, request
import logging

app = Flask(__name__)

@app.errorhandler(400)
def bad_request(error):
    return jsonify(
        error='Bad Request',
        message=str(error),
        status_code=400
    ), 400

@app.errorhandler(404)
def not_found(error):
    return jsonify(
        error='Not Found',
        message='The requested resource was not found',
        status_code=404
    ), 404

@app.errorhandler(500)
def internal_error(error):
    app.logger.error(f'Server Error: {error}')
    return jsonify(
        error='Internal Server Error',
        message='An unexpected error occurred',
        status_code=500
    ), 500

@app.route('/api/error-test')
def error_test():
    error_type = request.args.get('type', 'none')
    
    if error_type == '400':
        from flask import abort
        abort(400, description="Test bad request")
    elif error_type == '404':
        abort(404)
    elif error_type == '500':
        raise Exception("Test internal error")
    
    return jsonify(message='No error')

Streaming JSON

from flask import Flask, Response, stream_with_context
import json
import time

app = Flask(__name__)

@app.route('/api/stream')
def stream_json():
    def generate_data():
        yield '{"items": ['
        
        for i in range(100):
            if i > 0:
                yield ','
            
            item = {
                'id': i,
                'name': f'Item {i}',
                'timestamp': time.time()
            }
            
            yield json.dumps(item)
            time.sleep(0.1)  # Simulate processing
        
        yield ']}'
    
    return Response(
        stream_with_context(generate_data()),
        mimetype='application/json'
    )

@app.route('/api/json-lines')
def json_lines():
    """Stream JSON Lines format (one JSON object per line)."""
    def generate_lines():
        for i in range(50):
            item = {
                'id': i,
                'data': f'Record {i}',
                'processed_at': time.time()
            }
            yield json.dumps(item) + '\n'
            time.sleep(0.2)
    
    return Response(
        stream_with_context(generate_lines()),
        mimetype='application/x-ndjson'
    )

Custom JSON Provider

from flask import Flask
from flask.json.provider import DefaultJSONProvider
import orjson  # Fast JSON library

class OrjsonProvider(DefaultJSONProvider):
    """Custom JSON provider using orjson for better performance."""
    
    def dumps(self, obj, **kwargs):
        # orjson returns bytes, so decode to string
        return orjson.dumps(obj).decode('utf-8')
    
    def loads(self, s, **kwargs):
        return orjson.loads(s)

app = Flask(__name__)
app.json = OrjsonProvider(app)

@app.route('/api/fast')
def fast_json():
    # Large data structure
    data = {
        'items': [{'id': i, 'value': f'item_{i}'} for i in range(1000)]
    }
    
    from flask import jsonify
    return jsonify(data)

JSON Schema Validation

from flask import Flask, request, jsonify
import jsonschema
from jsonschema import validate, ValidationError

app = Flask(__name__)

# Define JSON schemas
USER_SCHEMA = {
    "type": "object",
    "properties": {
        "name": {"type": "string", "minLength": 1},
        "email": {"type": "string", "format": "email"},
        "age": {"type": "integer", "minimum": 0, "maximum": 150}
    },
    "required": ["name", "email"],
    "additionalProperties": False
}

def validate_json(schema):
    """Decorator to validate JSON against schema."""
    def decorator(f):
        def wrapper(*args, **kwargs):
            try:
                validate(request.get_json(), schema)
            except ValidationError as e:
                return jsonify(
                    error="Validation Error",
                    message=e.message,
                    path=list(e.path)
                ), 400
            except Exception as e:
                return jsonify(error="Invalid JSON"), 400
            
            return f(*args, **kwargs)
        
        wrapper.__name__ = f.__name__
        return wrapper
    return decorator

@app.route('/api/users', methods=['POST'])
@validate_json(USER_SCHEMA)
def create_user_validated():
    data = request.get_json()
    
    # Data is now guaranteed to be valid
    user = {
        'id': 123,
        'name': data['name'],
        'email': data['email'],
        'age': data.get('age')
    }
    
    return jsonify(user), 201

Install with Tessl CLI

npx tessl i tessl/pypi-flask

docs

blueprints.md

cli.md

configuration.md

context-globals.md

core-application.md

helpers.md

index.md

json-support.md

request-response.md

routing.md

sessions.md

signals.md

templates.md

testing.md

tile.json