skip to Main Content

In the JSON schema produced from a msgspec Struct, I’m wanting to output to the schema some text descriptions of the properties held within the Struct in the same way as the docstring of the Struct shows up in the JSON schema.

This little toy example (cut down from https://jcristharif.com/msgspec/jsonschema.html):

import json
import msgspec
from msgspec import Struct

def print_schema(schema):
    encoded_schema = msgspec.json.encode(schema)
    formatted_schema = json.dumps(json.loads(encoded_schema), indent=4)
    print(formatted_schema)

class Product(Struct):
    """A product in a catalog"""
    id: int
    name: str
    price: float

schema = msgspec.json.schema(Product)
print_schema(schema)

outputs:

{
    "$ref": "#/$defs/Product",
    "$defs": {
        "Product": {
            "title": "Product",
            "description": "A product in a catalog",
            "type": "object",
            "properties": {
                "id": {
                    "type": "integer"
                },
                "name": {
                    "type": "string"
                },
                "price": {
                    "type": "number"
                }
            },
            "required": [
                "id",
                "name",
                "price"
            ]
        }
    }
}

with description containing the docstring. I’d like to do something like

class Product(Struct):
    """A product in a catalog"""
    id: int      # DB uid
    name: str    # Name of product
    price: float # Price of product

and have the comments show up in the JSON schema against the appropriate property. Perhaps something like:

{
    "$ref": "#/$defs/Product",
    "$defs": {
        "Product": {
            "title": "Product",
            "description": "A product in a catalog",
            "type": "object",
            "properties": {
                "id": {
                    "description": "DB uid"
                    "type": "integer"
                },
                "name": {
                    "description": "Name of product"
                    "type": "string"
                },
                "price": {
                    "description": "Price of product"
                    "type": "number"
                }
            },
            "required": [
                "id",
                "name",
                "price"
            ]
        }
    }
}

However, I don’t know enough about JSON schemas to know if this is correct or valid although looking at https://json-schema.org/learn/getting-started-step-by-step it seems about right.

How can I do this using msgspec? Or maybe rewrite my code to use pydantic? Thanks.

2

Answers


  1. Chosen as BEST ANSWER

    With the confidence from the answer from https://stackoverflow.com/a/78703875/2746401, I had a dig around and found out how to do this with msgspec

    from typing import Annotated
    import json
    import msgspec
    from msgspec import Meta, Struct
    
    def print_schema(schema):
        encoded_schema = msgspec.json.encode(schema)
        formatted_schema = json.dumps(json.loads(encoded_schema), indent=4)
        print(formatted_schema)
    
    
    class Product(Struct):
        """A product in a catalog"""
        id: Annotated[int, Meta(description="DB uid")]
        name: Annotated[str, Meta(description="Name of product")]
        price: Annotated[float, Meta(description="Price of product")]
    
    schema = msgspec.json.schema(Product)
    print_schema(schema)
    

  2. Does this look like what you are looking for?

    import json
    
    from pydantic import BaseModel, Field
    
    
    class Product(BaseModel):
        """A product in a catalog"""
    
        id: int = Field(description="DB uid")
        name: str = Field(description="Name of product")
        price: float = Field(description="Price of product")
    
    
    product_schema = Product.model_json_schema()
    json_product_schema = json.dumps(product_schema, indent=2)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search