# \[dry-schema\] Key annotations

**URL:** <https://discourse.dry-rb.org/t/dry-schema-key-annotations/1544>\
**Category:** Ideas\
**Created:** [November 4, 2022, 11:08am UTC](https://discourse.dry-rb.org/t/dry-schema-key-annotations/1544 "2022-11-04T11:08:08Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![mehanoid](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/mehanoid/32/689_2.png) [@mehanoid](https://discourse.dry-rb.org/u/mehanoid)\
**Post date:** [November 4, 2022, 11:08am UTC](https://discourse.dry-rb.org/t/dry-schema-key-annotations/1544/1 "2022-11-04T11:08:08Z")

</div>

It would be very cool if it were possible to add annotations to keys, which can then be used to generate documentation.  
Proposed syntax:

```auto
ProductSchema = Dry::Schema.JSON do
    required(:name).filled(:string)
                   .annotate('name of the product')
    required(:price).filled(:decimal)
                    .annotate('price in USD')
end

```

Or:

```auto
ProductSchema = Dry::Schema.JSON do
    required(:name).filled(:string)
                   .description('name of the product')
    required(:price).filled(:decimal)
                    .description('price in USD')
end

```

You can use these annotations with json-schema and info extensions

```auto
ProductSchema.json_schema(description: true)
# {
# "$schema": "http://json-schema.org/draft-06/schema#",
# "type": "object",
# "properties": {
# "name": {"type": "string", "minLength": 1, "description": "name of the product"},
# "price": {"type": "number", "not": {"type": "null"}, "description": "price in USD"}
# },
# "required": ["name", "price"]
# }

```

```auto
ProductSchema.info
# {
# keys: {
# name: { required: true, type: 'string', description: 'name of the product' },
# price: { required: true, type: 'float', description: 'price in USD' }
# }
# }

```

What do you think? I could probably try making a PR if there is interest in merging it.

---

<div class="post-metadata">

**Author:** ![alassek](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/alassek/32/314_2.png) [@alassek](https://discourse.dry-rb.org/u/alassek)\
**Post date:** [November 4, 2022, 10:14pm UTC](https://discourse.dry-rb.org/t/dry-schema-key-annotations/1544/2 "2022-11-04T22:14:42Z")

</div>

There [was some discussion earlier](https://discourse.dry-rb.org/t/getting-dry-types-metadata-into-dry-schemas-json-schema-output/1439) about this, I have not seen any PRs come out of it though.

---

<div class="post-metadata">

**Author:** ![mehanoid](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/mehanoid/32/689_2.png) [@mehanoid](https://discourse.dry-rb.org/u/mehanoid)\
**Post date:** [November 7, 2022, 11:39pm UTC](https://discourse.dry-rb.org/t/dry-schema-key-annotations/1544/3 "2022-11-07T23:39:52Z")

</div>

Thanks for pointing that out. That discussion is about using metadata from custom dry-types. However, I wrote about adding `description` to the dry-schema definition using built-in types.  
Perhaps we could combine both. Then when generating a json-schema, the metadata would be taken from the dry-schema definition first, and then from the type. Being able to add `example` to the dry-schema definition would also be nice.  
I don’t like to wrap metadata in an optional `json_schema` key, because that would be cumbersome in the dry-schema definition. Also, I think it would be better not to bind exactly to JSON schema, since the `description` and `example` metadata could be used by other extensions and compilers as well.  
But at the same time, I’m not quite sure if the `meta` method is intended to define data to be used by built-in extensions, not for some custom purpose, and whether conflicts with other metadata are possible. 🤔

If using metadata, we could extend the dry-schema DSL with the `.meta` method, delegating parameters to the dry-type `.meta` method or storing them in its own instance variables.

Thus I could imagine something like this:

```auto
module Types
  include Dry.Types()

  Email = self::String.meta(
    description: 'An email address',
    example: 'person@example.com',
  )
end

ProductSchema = Dry::Schema.JSON do
  required(:name).filled(:string).meta(
    description: 'Name of the product',
    example: 'Phone'
  )
  required(:price).filled(:decimal).meta(
    description: 'Price in USD',
    example: '999,99',
  )
  optional(:vendor_email).filled(Email)
end

ProductSchema.json_schema(meta: true)
# {
# "$schema": "http://json-schema.org/draft-06/schema#",
# "type": "object",
# "properties": {
# "name": {"type": "string", "minLength": 1, "description": "Name of the product", "example": "Phone"},
# "price": {"type": "number", "not": {"type": "null"}, "description": "Price in USD", "example": "999,99"},
# "vendor_email": {"type": "string", "description": "An email address", "example": "person@example.com"}
# },
# "required": ["name", "price"]
# }

```

---

<div class="post-metadata">

**Author:** ![alassek](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/alassek/32/314_2.png) [@alassek](https://discourse.dry-rb.org/u/alassek)\
**Post date:** [November 8, 2022, 7:33pm UTC](https://discourse.dry-rb.org/t/dry-schema-key-annotations/1544/4 "2022-11-08T19:33:49Z")

</div>

I would suggest going in a slightly different direction with this… there is already a facility for mapping I18n files to schema errors, why not expand this for annotations?

If you have annotations in one language, you may very well want to support additional.

> **[dry-rb - dry-schema v1.10 - Error messages](https://dry-rb.org/gems/dry-schema/1.10/error-messages/)**
>
> Flexible validation library for data structures in Ruby

---

<div class="post-metadata">

**Author:** ![mehanoid](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/mehanoid/32/689_2.png) [@mehanoid](https://discourse.dry-rb.org/u/mehanoid)\
**Post date:** [November 21, 2022, 8:40am UTC](https://discourse.dry-rb.org/t/dry-schema-key-annotations/1544/5 "2022-11-21T08:40:58Z")

</div>

Yeah, I guess translations will be the most universal way. Although originally I had an idea to merge json schema generation result with some hash without any changes in dry-schema. And then I started thinking about how to avoid duplication of field list. But of course, describing annotations in the schema itself isn’t quite the SRP and universal way. And at the same time it would be nice to have a way to describe for annotations in the gem itself.  
Maybe I’ll find time to make a PR, but I won’t promise yet 🙂

---

<div class="post-metadata">

**Author:** ![phaedryx](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/phaedryx/32/998_2.png) [@phaedryx](https://discourse.dry-rb.org/u/phaedryx)\
**Post date:** [February 5, 2025, 10:53pm UTC](https://discourse.dry-rb.org/t/dry-schema-key-annotations/1544/6 "2025-02-05T22:53:19Z")

</div>

I’m also looking for a way to add annotations to my JSON schemas generated from my `Dry::Schema`’s
