Fabulous.AST.Build
2.0.0-pre01
See the version list below for details.
dotnet add package Fabulous.AST.Build --version 2.0.0-pre01
NuGet\Install-Package Fabulous.AST.Build -Version 2.0.0-pre01
<PackageReference Include="Fabulous.AST.Build" Version="2.0.0-pre01"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="Fabulous.AST.Build" Version="2.0.0-pre01" />
<PackageReference Include="Fabulous.AST.Build"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add Fabulous.AST.Build --version 2.0.0-pre01
#r "nuget: Fabulous.AST.Build, 2.0.0-pre01"
#:package Fabulous.AST.Build@2.0.0-pre01
#addin nuget:?package=Fabulous.AST.Build&version=2.0.0-pre01&prerelease
#tool nuget:?package=Fabulous.AST.Build&version=2.0.0-pre01&prerelease
Fabulous.AST.Build
Automatically generate F# types from JSON files at build time.
Overview
Fabulous.AST.Build is an MSBuild task that:
- Watches JSON files in your project
- Automatically generates F# record types during build
- Supports incremental builds (only regenerates when JSON changes)
- Integrates seamlessly with MSBuild and .NET CLI
Use cases:
- Generate F# types from API response samples
- Keep type definitions in sync with JSON schemas
- Automate type generation in CI/CD pipelines
💡 Tip: For programmatic control over generation, use Fabulous.AST.Json directly.
Installation
dotnet add package Fabulous.AST.Build
Requirements: .NET 8.0 or later
Tutorial
Step 1: Create a JSON Schema File
Create a folder for your JSON schemas and add a sample file.
schemas/user.json:
{
"id": 1,
"name": "Alice",
"email": "alice@example.com",
"isActive": true
}
Step 2: Configure Your Project
Add the FabulousAstJson item to your .fsproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Fabulous.AST.Build" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<FabulousAstJson Include="schemas/user.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="Generated/user.Generated.fs" />
</ItemGroup>
</Project>
Step 3: Build Your Project
dotnet build
This generates Generated/user.Generated.fs:
// Auto-generated from schemas/user.json
// Hash: abc123...
// Do not edit manually - changes will be overwritten
type User = {
id: int
name: string
email: string
isActive: bool
}
Step 4: Custom Root Type Name
By default, the root type name is derived from the filename. Override it with RootName:
<ItemGroup>
<FabulousAstJson Include="schemas/api-response.json" RootName="ApiResponse" />
</ItemGroup>
Step 5: Add a Namespace
Wrap generated types in a namespace:
<ItemGroup>
<FabulousAstJson Include="schemas/user.json"
RootName="User"
Namespace="MyApp.Models" />
</ItemGroup>
Output:
namespace MyApp.Models
type User = {
id: int
name: string
email: string
isActive: bool
}
Step 6: Use a Module Instead
Use ModuleName for a module wrapper:
<ItemGroup>
<FabulousAstJson Include="schemas/user.json"
RootName="User"
ModuleName="MyApp.Models" />
</ItemGroup>
Output:
module MyApp.Models
type User = {
id: int
name: string
email: string
isActive: bool
}
Step 7: Multiple JSON Files
Process multiple schemas with different configurations:
<ItemGroup>
<FabulousAstJson Include="schemas/user.json"
RootName="User"
Namespace="MyApp.Models" />
<FabulousAstJson Include="schemas/product.json"
RootName="Product"
Namespace="MyApp.Models" />
<FabulousAstJson Include="schemas/order.json"
RootName="CustomerOrder"
Namespace="MyApp.Orders" />
</ItemGroup>
<ItemGroup>
<Compile Include="Generated/user.Generated.fs" />
<Compile Include="Generated/product.Generated.fs" />
<Compile Include="Generated/order.Generated.fs" />
</ItemGroup>
Step 8: Custom Output Directory
Change where generated files are placed:
<PropertyGroup>
<FabulousAstJsonOutputDir>Types/</FabulousAstJsonOutputDir>
</PropertyGroup>
Step 9: Glob Patterns
Process all JSON files in a directory:
<ItemGroup>
<FabulousAstJson Include="schemas/**/*.json" />
</ItemGroup>
Step 10: Custom Output Filename
Override the default {filename}.Generated.fs pattern:
<ItemGroup>
<FabulousAstJson Include="schemas/user.json"
OutputFileName="UserTypes.fs" />
</ItemGroup>
Configuration Reference
Project Properties
| Property | Default | Description |
|---|---|---|
FabulousAstJsonOutputDir |
$(MSBuildProjectDirectory)\Generated\ |
Output directory for generated files |
EnableFabulousAstJsonGeneration |
true |
Enable/disable generation (useful for CI) |
Item Metadata
| Metadata | Default | Description |
|---|---|---|
RootName |
Root |
Name of the root type |
Namespace |
(empty) | Namespace to wrap types in |
ModuleName |
(empty) | Module to wrap types in (alternative to Namespace) |
OutputFileName |
{InputName}.Generated.fs |
Custom output filename |
Type Inference
The generator infers F# types from JSON values:
| JSON Value | F# Type |
|---|---|
"string" |
string |
123 |
int |
9999999999 |
int64 |
123.45 |
float |
true/false |
bool |
null |
obj |
[...] |
ElementType list |
{...} |
Record type |
Arrays Become List Types
Input (users.json):
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
]
Output:
type UsersItem = { id: int; name: string }
type Users = UsersItem list
Nested Objects Become Nested Types
Input (company.json):
{
"name": "Acme Corp",
"address": {
"street": "123 Main St",
"city": "London"
}
}
Output:
type Address = { street: string; city: string }
type Company = { name: string; address: Address }
Optional Fields
Fields missing or null in some array objects become option types:
Input:
[
{ "id": 1, "name": "Alice", "nickname": "Ali" },
{ "id": 2, "name": "Bob" }
]
Output:
type RootItem = { id: int; name: string; nickname: string option }
type Root = RootItem list
Special Field Name Handling
Leading Digits
JSON fields starting with digits are prefixed with _:
{ "2faEnabled": true }
Generates:
type Root = { _2faEnabled: bool }
Reserved Keywords
F# keywords are escaped with double backticks:
{ "type": "admin", "class": "premium" }
Generates:
type Root = { ``type``: string; ``class``: string }
Incremental Builds
The task uses content hashing for smart rebuilds:
- Files are only regenerated when JSON content changes
- Configuration changes (RootName, Namespace, etc.) trigger regeneration
- Generated files include a hash comment for verification
Troubleshooting
Generated File Not Updating
Ensure the file is included as
FabulousAstJson:<FabulousAstJson Include="path/to/file.json" />Ensure the generated file is in
Compile:<Compile Include="Generated/file.Generated.fs" />Try a clean rebuild:
dotnet clean && dotnet build
Task Assembly Not Found
If you see "Skipping generation because task assembly not found":
- Ensure you've restored packages:
dotnet restore - For local development, build Fabulous.AST.Build first
Disable Generation
Disable generation for CI or specific builds:
<PropertyGroup>
<EnableFabulousAstJsonGeneration>false</EnableFabulousAstJsonGeneration>
</PropertyGroup>
Or via command line:
dotnet build -p:EnableFabulousAstJsonGeneration=false
Related Packages
- Fabulous.AST - Core DSL for generating F# code
- Fabulous.AST.Json - Programmatic API for JSON-to-F# generation
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- No dependencies.
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 | 44 | 6/2/2026 |
| 2.0.0-pre07 | 60 | 5/30/2026 |
| 2.0.0-pre06 | 88 | 1/9/2026 |
| 2.0.0-pre05 | 214 | 12/19/2025 |
| 2.0.0-pre04 | 244 | 12/15/2025 |
| 2.0.0-pre03 | 143 | 12/13/2025 |
| 2.0.0-pre02 | 101 | 12/12/2025 |
| 2.0.0-pre01 | 88 | 12/12/2025 |
### Breaking Changes
- Widget builders now return unified base types instead of specific node types
- Raw SyntaxOak nodes must now be wrapped with EscapeHatch when yielding into collections
- Removed obsolete per-node modifiers
### Added
- Unified modifier extensions for widget types
- New EscapeHatch widget for wrapping raw SyntaxOak nodes
- New single-clause overloads for Match and Try expressions
- Parallel test execution enabled
### Changed
- Refactored widget systems to use shared attribute sets
- Internal widget key handlers now wrap nodes appropriately
### Fixed
- Widget key generation fixes