Fabulous.AST.Json
2.0.0-pre08
dotnet add package Fabulous.AST.Json --version 2.0.0-pre08
NuGet\Install-Package Fabulous.AST.Json -Version 2.0.0-pre08
<PackageReference Include="Fabulous.AST.Json" Version="2.0.0-pre08" />
<PackageVersion Include="Fabulous.AST.Json" Version="2.0.0-pre08" />
<PackageReference Include="Fabulous.AST.Json" />
paket add Fabulous.AST.Json --version 2.0.0-pre08
#r "nuget: Fabulous.AST.Json, 2.0.0-pre08"
#:package Fabulous.AST.Json@2.0.0-pre08
#addin nuget:?package=Fabulous.AST.Json&version=2.0.0-pre08&prerelease
#tool nuget:?package=Fabulous.AST.Json&version=2.0.0-pre08&prerelease
Fabulous.AST.Json
Generate F# types from JSON samples using the Fabulous.AST DSL.
Overview
Fabulous.AST.Json is a programmatic F# type generator that:
- Takes a JSON sample as input
- Infers F# record types, nested types, and type aliases
- Outputs clean, Fantomas-formatted F# code
It is NOT:
- A runtime JSON deserializer (use
System.Text.JsonorNewtonsoft.Jsonfor that) - A Type Provider (types are generated as source code, not at compile-time)
Use cases:
- Generating F# types from API response samples
- Creating type-safe models from JSON schemas
- Test fixtures and documentation
- Custom code generation tooling
💡 Tip: For automatic build-time generation from JSON files, use Fabulous.AST.Build instead.
Installation
dotnet add package Fabulous.AST.Json
Requirements: .NET 8.0 or later
Tutorial
Step 1: Basic Type Generation
The simplest use case is generating a record type from a JSON object:
open Fabulous.AST
open Fabulous.AST.Json
open type Ast
let json = """{ "name": "Alice", "age": 30, "active": true }"""
let source =
Oak() {
AnonymousModule() {
Json(json)
}
}
|> Gen.mkOak
|> Gen.run
printfn "%s" source
Output:
type Root = { name: string; age: int; active: bool }
Step 2: Custom Root Type Name
By default, the root type is named Root. Use .rootName() to customize it:
let json = """{ "id": 1, "email": "alice@example.com" }"""
let source =
Oak() {
AnonymousModule() {
Json(json).rootName("User")
}
}
|> Gen.mkOak
|> Gen.run
Output:
type User = { id: int; email: string }
Step 3: Nested Objects
Nested JSON objects become nested record types:
let json = """
{
"user": {
"name": "Alice",
"address": {
"city": "London",
"country": "UK"
}
}
}
"""
let source =
Oak() {
AnonymousModule() {
Json(json).rootName("Response")
}
}
|> Gen.mkOak
|> Gen.run
Output:
type Address = { city: string; country: string }
type User = { name: string; address: Address }
type Response = { user: User }
Step 4: Arrays
Arrays generate an element type and a list alias:
let json = """
[
{ "id": 1, "name": "Item 1" },
{ "id": 2, "name": "Item 2" }
]
"""
let source =
Oak() {
AnonymousModule() {
Json(json).rootName("Products")
}
}
|> Gen.mkOak
|> Gen.run
Output:
type ProductsItem = { id: int; name: string }
type Products = ProductsItem list
Step 5: Optional Fields
When analyzing arrays of objects, fields that are missing or null in some objects become option types:
let json = """
[
{ "id": 1, "name": "Alice", "nickname": "Ali" },
{ "id": 2, "name": "Bob" }
]
"""
let source =
Oak() {
AnonymousModule() {
Json(json).rootName("Users")
}
}
|> Gen.mkOak
|> Gen.run
Output:
type UsersItem = { id: int; name: string; nickname: string option }
type Users = UsersItem list
Step 6: Relaxed JSON Parsing
Handle JSON with comments and trailing commas:
let json = """
{
// This is a comment
"id": 1,
"name": "Test", // trailing comma
}
"""
let source =
Oak() {
AnonymousModule() {
Json(json)
.documentAllowTrailingCommas(true)
.documentCommentHandling(System.Text.Json.JsonCommentHandling.Skip)
}
}
|> Gen.mkOak
|> Gen.run
Step 7: Case-Insensitive Property Names
When JSON has inconsistent casing, use case-insensitive matching:
let json = """
[
{ "ID": 1, "Name": "First" },
{ "id": 2, "name": "Second" }
]
"""
let source =
Oak() {
AnonymousModule() {
Json(json).nodePropertyNameCaseInsensitive(true)
}
}
|> Gen.mkOak
|> Gen.run
Step 8: Adding to a Namespace or Module
Wrap generated types in a namespace:
let json = """{ "id": 1, "name": "Alice" }"""
let source =
Oak() {
Namespace("MyApp.Models") {
Json(json).rootName("User")
}
}
|> Gen.mkOak
|> Gen.run
Output:
namespace MyApp.Models
type User = { id: int; name: string }
Or in a module:
let source =
Oak() {
Module("MyApp.Models") {
Json(json).rootName("User")
}
}
|> Gen.mkOak
|> Gen.run
Output:
module MyApp.Models
type User = { id: int; name: string }
Type Inference Rules
| JSON Value | F# Type |
|---|---|
"string" |
string |
123 |
int |
9999999999 (large integer) |
int64 |
123.45 |
float |
true / false |
bool |
null |
obj |
[...] |
ElementType list |
{...} |
Record type |
Special Field Name Handling
Leading Digits
JSON fields starting with digits are prefixed with _:
{ "2faEnabled": true, "3rdPartyId": "abc" }
Generates:
type Root = { _2faEnabled: bool; _3rdPartyId: string }
F# Reserved Keywords
JSON fields that are F# keywords are escaped with double backticks:
{ "type": "admin", "class": "premium" }
Generates:
type Root = { ``type``: string; ``class``: string }
API Reference
Available Modifiers
| Modifier | Description |
|---|---|
.rootName(string) |
Set the name of the root type (default: "Root") |
.documentOptions(JsonDocumentOptions) |
Provide JsonDocumentOptions for parsing |
.documentAllowTrailingCommas(bool) |
Allow trailing commas in JSON |
.documentCommentHandling(JsonCommentHandling) |
Handle JSON comments |
.documentMaxDepth(int) |
Maximum nesting depth |
.serializerOptions(JsonSerializerOptions) |
Seed document options from a serializer config |
.nodePropertyNameCaseInsensitive(bool) |
Case-insensitive property matching |
Related Packages
- Fabulous.AST - Core DSL for generating F# code
- Fabulous.AST.Build - MSBuild task for automatic build-time generation
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Fabulous.AST (>= 2.0.0-pre08)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0-pre08 | 41 | 6/2/2026 |
| 2.0.0-pre07 | 53 | 5/30/2026 |
| 2.0.0-pre06 | 90 | 1/9/2026 |
| 2.0.0-pre05 | 229 | 12/19/2025 |
| 2.0.0-pre04 | 255 | 12/15/2025 |
| 2.0.0-pre03 | 157 | 12/13/2025 |
| 2.0.0-pre02 | 110 | 12/12/2025 |
| 2.0.0-pre01 | 101 | 12/12/2025 |
### Fixed
- JSON field names containing backticks now replace them with underscores instead of producing an invalid nested-backtick identifier (#195)