# Optional / null values

By design, all fields are required, ie. `null` or missing fields will cause a `TypeError` while reviving. In the case of the `Animal` class from the [introductory example](https://github.com/javiercejudo/modelico/tree/c356c97466264d859bea3d0ad8f9542f3bfd0894/docs/introduction/README.md):

```javascript
const pet = M.fromJSON(Animal, '{"name": null}')
// => TypeError: no value for key "name"
```

To support missing properties or `null` values, you can either use `withDefault` or declare the property as a `Maybe`

## Using `withDefault`

The `withDefault` metadata takes some metadata and a default value which will be used only if the property is `null` or missing.

```javascript
import M from 'modelico'
const {string, maybe} = M.metadata()

class Animal extends M.Base {

  // ... same as before

  static innerTypes () {
    return Object.freeze({
      name: withDefault(string(), 'Unknown')
    })
  }
}
```

Then, it can be used as any other value:

```javascript
const pet1 = M.fromJSON(Animal, '{"name": "Bane"}')
const pet2 = M.fromJSON(Animal, '{"name": null}')
const pet3 = M.fromJSON(Animal, '{}')

pet1.name() // => Bane
pet2.name() // => Unknown
pet3.name() // => Unknown
```

## Maybes

```javascript
import M from 'modelico'
const {string, maybe} = M.metadata()

class Animal extends M.Base {

  // ... same as before

  static innerTypes () {
    return Object.freeze({
      name: maybe(string())
    })
  }
}
```

Then, we can use it as follows:

```javascript
const pet1 = M.fromJSON(Animal, '{"name": "Bane"}')
// pet2 and pet3 behave the same way
const pet2 = M.fromJSON(Animal, '{"name": null}')
const pet3 = M.fromJSON(Animal, '{}')

pet1.name().isEmpty()         // => false
pet1.name().getOrElse('Coco') // => Bane
JSON.stringify(pet1)          // => {"name":"Bane"}

pet2.name().isEmpty()         // => true
pet2.name().getOrElse('Bane') // => Bane
JSON.stringify(pet2)          // => {"name":null}

pet3.name().isEmpty()         // => true
pet3.name().getOrElse('Bane') // => Bane
JSON.stringify(pet3)          // => {"name":null}
```

*Note: `pet2` does not produce the same JSON it was parsed from. If that is important to you, one possibility would be to not declare the `name` field and use `M.fields(pet2).name` to check for its presence and value manually.*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://modelico.javiercejudo.com/basics/optional_values.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
