diff --git a/.bonsai/.gitignore b/.bonsai/.gitignore
new file mode 100644
index 0000000..cceac95
--- /dev/null
+++ b/.bonsai/.gitignore
@@ -0,0 +1,13 @@
+# Bonsai scripting files
+.vs
+.vscode
+bin
+obj
+Packages
+Bonsai.exe.WebView2
+*.bin
+*.avi
+*.dll
+*.exe
+*.exe.settings
+*.bonsai.layout
\ No newline at end of file
diff --git a/.bonsai/Bonsai.config b/.bonsai/Bonsai.config
new file mode 100644
index 0000000..1fa28c4
--- /dev/null
+++ b/.bonsai/Bonsai.config
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.bonsai/NuGet.config b/.bonsai/NuGet.config
new file mode 100644
index 0000000..fa620e4
--- /dev/null
+++ b/.bonsai/NuGet.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/.bonsai/setup.cmd b/.bonsai/setup.cmd
new file mode 100644
index 0000000..3c53f3a
--- /dev/null
+++ b/.bonsai/setup.cmd
@@ -0,0 +1 @@
+powershell -ExecutionPolicy Bypass -File .\setup.ps1
\ No newline at end of file
diff --git a/.bonsai/setup.ps1 b/.bonsai/setup.ps1
new file mode 100644
index 0000000..01cfba6
--- /dev/null
+++ b/.bonsai/setup.ps1
@@ -0,0 +1,21 @@
+Push-Location $PSScriptRoot
+if (!(Test-Path "./Bonsai.exe")) {
+ $release = "https://github.com/bonsai-rx/bonsai/releases/latest/download/Bonsai.zip"
+ $configPath = "./Bonsai.config"
+ if (Test-Path $configPath) {
+ [xml]$config = Get-Content $configPath
+ $bootstrapper = $config.PackageConfiguration.Packages.Package.where{$_.id -eq 'Bonsai'}
+ if ($bootstrapper) {
+ $version = $bootstrapper.version
+ $release = "https://github.com/bonsai-rx/bonsai/releases/download/$version/Bonsai.zip"
+ }
+ }
+ Invoke-WebRequest $release -OutFile "temp.zip"
+ Move-Item -Path "NuGet.config" "temp.config" -ErrorAction SilentlyContinue
+ Expand-Archive "temp.zip" -DestinationPath "." -Force
+ Move-Item -Path "temp.config" "NuGet.config" -Force -ErrorAction SilentlyContinue
+ Remove-Item -Path "temp.zip"
+ Remove-Item -Path "Bonsai32.exe"
+}
+& .\Bonsai.exe --no-editor
+Pop-Location
\ No newline at end of file
diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
new file mode 100644
index 0000000..8b3ab7e
--- /dev/null
+++ b/.config/dotnet-tools.json
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "bonsai.sgen": {
+ "version": "0.4.0",
+ "commands": [
+ "bonsai.sgen"
+ ],
+ "rollForward": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bonsai.Sgen/CSharpClassTemplate.cs b/Bonsai.Sgen/CSharpClassTemplate.cs
index 001596f..38a9b30 100644
--- a/Bonsai.Sgen/CSharpClassTemplate.cs
+++ b/Bonsai.Sgen/CSharpClassTemplate.cs
@@ -121,7 +121,7 @@ public override void BuildType(CodeTypeDeclaration type)
nameof(JsonPropertyAttribute.Required),
new CodeFieldReferenceExpression(
new CodeTypeReferenceExpression(typeof(Required)),
- nameof(Required.Always))));
+ property.IsNullable ? nameof(Required.AllowNull) : nameof(Required.Always))));
}
propertyDeclaration.CustomAttributes.Add(jsonProperty);
}
diff --git a/docs/articles/advanced-usage.md b/docs/articles/advanced-usage.md
new file mode 100644
index 0000000..ceb7fce
--- /dev/null
+++ b/docs/articles/advanced-usage.md
@@ -0,0 +1,111 @@
+---
+uid: advanced-usage
+---
+
+
+## Unions
+
+In the previous examples, we have seen how create object properties of a single type. However, in practice, data structures' fields can often be represented by one of several types. We have actually seen a special case of this behavior in the previous nullable example, where a field can be either a value of a given type or `null` (or an Union between type `T` and `null`).
+
+Similarly, `json-schema` allows union types to be defined using the `oneOf` keyword. For example, consider the following schema:
+
+```json
+{
+ "title": "MyPet",
+ "type": "object",
+ "properties": {
+ "FooProperty": {
+ "oneOf": [
+ { "type": "string" },
+ { "type": "number" }
+ ]
+ }
+ }
+}
+```
+
+If we run `Bonsai.Sgen` on this schema, we will get the following signature for the `FooProperty` property:
+
+```csharp
+public object FooProperty
+```
+
+This is because while the `oneOf` keyword is supported by the `Bonsai.Sgen` tool, for statically typed languages like `C#` and `Bonsai`, we need to know the exact type of the property at compile time. As a result, we opt to "up-cast" the property to the most general type that can represent all the possible types in the union (`object`). It is up to the user to down-cast the property to the correct type at runtime.
+
+
+## Tagged Unions
+
+At this point, you might be wondering if there is a way to represent union types in a more type-safe way in json-schema. The answer is yes, and the way to do it is by using [`discriminated unions`](https://en.wikipedia.org/wiki/Tagged_union) (or `tagged union`). The syntax for discriminated unions is not supported by vanilla `json-schema`, but it is supported by the [`OpenAPI` standard](https://swagger.io/docs/specification/v3_0/data-models/inheritance-and-polymorphism/#discriminator), which is a superset of `json-schema`. The key idea behind discriminated unions is to add a `discriminator` field to the schema that specifies the property that will be used to determine the type of the object at runtime.
+
+For example, a `Pet` object that can be either a `Dog` or a `Cat` can be represented as follows:
+
+[person](~/workflows/person-and-discriminated-pets.json)
+
+```json
+"Pet": {
+ "discriminator": {
+ "mapping": {
+ "cat": "#/definitions/Cat",
+ "dog": "#/definitions/Dog"
+ },
+ "propertyName": "pet_type"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/definitions/Dog"
+ },
+ {
+ "$ref": "#/definitions/Cat"
+ }
+ ]
+ }
+```
+
+In `C#`, `Bonsai.Sgen` will generate a root type `Pet` that will be inherited by the `Dog` and `Cat` types (since in the worst case scenario, the discriminated property must be shared). The `Pet` type will have a `pet_type` property that will be used to downcast to the proper type at runtime. At this point we can open our example in `Bonsai` and see how the `Pet` type is represented in the workflow.
+
+As you can see below, we still get a `Pet` type. Better than `object` but still not a `Dog` or `Cat` type. Fortunately, `Bonsai.Sgen` will generate an operator that can be used to filter and downcast the `Pet` objects to the correct type at runtime. These are called `Match` operators. After adding a `MatchPet` to our workflow we can select the desired target type which will allow us access to the properties of the `Dog` or `Cat` type. Conversely, we can also upcast a `Dog` or `Cat` to a `Pet` leaving the `MatchPet` operator's `Type` property empty.
+
+:::workflow
+
+:::
+
+> [!Important]
+> In is general advisable to use references in the `oneOf` syntax. Not only does this decision make your `json-schema` significantly smaller, it will also help `Bonsai.Sgen` generate the correct class hierarchy if multiple unions are present in the schema. If you use inline objects, `Bonsai.Sgen` will likely have to generate a new root class for each union, which can lead to a lot of duplicated code and a more complex object hierarchy.
+
+
+
+## Extending generated code with `partial` classes
+
+Since `Bonsai.Sgen` will generate proper `class` for each object in the schema, it is possible to use these types to create custom operators and methods using the `Scriping Extensions` feature of `Bonsai`. However, sometimes we may want to extend the features of the generated classes directly...
+
+For those that inspected the general `C#` code, you will notice that all classes are marked as [`partial`](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods). This is a feature of `C#` that allows a class to be split. This was a deliberate design choice to allow users to extend the generated code. However, because it is usually always a bad idea to modify generated code directly (e.g. we may want to regenerate it in the future), `partial` classes allows modification to be made in a separate file.
+
+Suppose we want to sum `Cats`, we can overload the operator with a small method in a separate file::
+
+```csharp
+namespace PersonAndDiscriminatedPets
+{
+ partial class Cat{
+ public static Cat operator +(Cat c1, Cat c2)
+ {
+ return new Cat
+ {
+ CanMeow = c1.CanMeow || c2.CanMeow,
+ Age = c1.Age + c2.Age
+ };
+ }
+ }
+}
+```
+
+In `Bonsai`, we can now use the `Add` operator to sum `Cats`:
+
+
+:::workflow
+
+:::
+
+
+## Other supported tags
+
+- `x-abstract`: This tag is used to mark a class as abstract. An abstract class will not be generated as an operator in Bonsai. This may be useful for root classes of unions that may never need to be manipulated in Bonsai.
\ No newline at end of file
diff --git a/docs/articles/basic-usage.md b/docs/articles/basic-usage.md
new file mode 100644
index 0000000..d782e6c
--- /dev/null
+++ b/docs/articles/basic-usage.md
@@ -0,0 +1,221 @@
+---
+uid: basic-usage
+---
+
+
+## Automatic generation of Bonsai code using Bonsai.Sgen
+
+We will expand this example later on, but for now, let's see how we can use `Bonsai.Sgen` to automatically generate the Bonsai code for the `Person` object.
+
+First, we need to define the schema of the object in a JSON file:
+
+[person](~/workflows/person.json)
+
+```json
+{
+ "title": "Person",
+ "type": "object",
+ "properties": {
+ "Age": { "type": "integer" },
+ "FirstName": { "type": "string" },
+ "LastName": { "type": "string" },
+ "DOB": { "type": "string", "format": "date-time" }
+ }
+}
+```
+
+Second, we need to run the `Bonsai.Sgen` tool to generate the Bonsai code:
+
+```cmd
+dotnet bonsai.sgen --schema docs/workflows/person.json --output docs/workflows/Extensions/PersonSgen.cs
+```
+
+Finally, we can use the generated code in our Bonsai workflow:
+
+:::workflow
+
+:::
+
+As you can probably tell, the `Bonsai.Sgen` approach is much more concise and less error-prone than the previous ones. It allows you to focus on the data structure itself and not on the boilerplate code required to create it in Bonsai. Moreover, as we will see later, the tool also automatically generates serialization and deserialization boilerplate code for the object, which can be very useful when working with external data sources.
+
+Finally, if one considers the `json-schema` as the "source of truth" for the data structure representation, it is possible to generate multiple representations of the object in different languages, ensuring interoperability. This can be very useful when working in a multi-language environment (e.g. running experiment in Bonsai and analysis in Python) and when sharing data structures across different projects.
+
+## Multiple objects
+
+The previous example shows how a single record can be modelled. In practice, projects often require modelling different types of objects. This is where `Bonsai.Sgen` shines, as it allows you to generate multiple objects from a single schema file:
+
+[person_and_dog](~/workflows/person-and-dog.json)
+
+```json
+{
+ "title": "PersonAndPet",
+ "definitions": {
+ "Person": {
+ "title": "Person",
+ "type": "object",
+ "properties": {
+ "Age": { "type": "integer" },
+ "FirstName": { "type": "string" },
+ "LastName": { "type": "string" },
+ "DOB": { "type": "string", "format": "date-time" }
+ }
+ },
+ "Dog": {
+ "title": "Dog",
+ "type": "object",
+ "properties": {
+ "Name": { "type": "string" },
+ "Breed": { "type": "string" },
+ "Age": { "type": "integer" }
+ }
+ }
+ },
+ "type": "object",
+ "properties": {
+ "owner": { "$ref": "#/definitions/Person" },
+ "pet": { "$ref": "#/definitions/Dog" }
+ }
+}
+```
+
+```cmd
+dotnet bonsai.sgen --schema docs/workflows/person_and_dog.json --output docs/workflows/Extensions/PersonAndDogSgen.cs --namespace PersonAndDog
+```
+
+:::workflow
+
+:::
+
+A few things worth noting in this example:
+
+- The schema file contains two definitions: `Person` and `Dog` that give rise to two operators (`Person` and `Dog`) in the generated code.
+- A third definition `PersonAndPet` is used to combine the two objects into a single record. This can be omitted as we will see later by using the `x-abstract` property.
+- The `--namespace` flag is used to specify the namespace of the generated code. This is useful to prevent name clashes between different schemas (e.g. `PersonAndDog.Person` and `Person` from the previous example).
+- Both `Person` and `Dog` `json-schema` objects are passed as references. This is extremely important as it allows the reuse of the same definition in multiple places. This is particularly useful when working with complex data structures that share common fields. If definitions are passed in-line (i.e. redefined each time), Bonsai.Sgen may not be able to correctly identify them as the same object.
+
+## Nested objects
+
+The previous example highlights the simplicity of generating Bonsai code for simple objects. However, the real power of `Bonsai.Sgen` comes when dealing with more complex data structures, such as nested objects. Moreover, Bonsai syntax lends itself quite nicely to represent these nested structures as well as build them:
+
+
+:::workflow
+
+:::
+
+## Enums
+
+`Bonsai.Sgen` also supports the generation of enums using the `enum` type in the `json-schema`:
+
+We can replace the `Pet` object in the previous example with an [`enum`](https://json-schema.org/understanding-json-schema/reference/enum):
+
+[Pet as Enum](~/workflows/person-and-pet-enum.json).
+
+```json
+(...)
+ {
+ "Pet": {
+ "title": "Pet",
+ "type": "string",
+ "enum": ["Dog", "Cat", "Fish", "Bird", "Reptile"]
+ }
+ },
+ "type": "object",
+ "properties": {
+ "owner": {"$ref": "#/definitions/Person"},
+ "pet": {"$ref": "#/definitions/Pet"}
+ }
+```
+
+In Bonsai, they can be manipulated as [`Enum`](https://learn.microsoft.com/en-us/dotnet/api/system.enum?view=net-9.0) types:
+
+:::workflow
+
+:::
+
+> [!TIP]
+> In certain cases, it may be useful to use `x-enum-names` to specify the rendered names of the enum values.
+>
+> ```json
+> {
+> "MyIntEnum": {
+> "enum": [0, 1, 2, 3, 4],
+> "title": "MyIntEnum",
+> "type": "integer",
+> "x-enumNames": ["None", "One", "Two", "Three", "Four"]
+> }
+> }
+> ```
+
+## Lists
+
+`Bonsai.Sgen` also supports the generation of lists using the `array` type in the `json-schema`:
+
+```json
+ "pets": {
+ "type": "array",
+ "items": {"$ref": "#/definitions/Pet"}
+ }
+```
+
+`json-schema` `array`s will be rendered as [`List`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=net-9.0) in the generated code and can be manipulated (and created) as such.
+
+:::workflow
+
+:::
+
+## Nullable types
+
+`json-schema` supports the `null` type, which can be used to represent nullable types. The standard is a bit loose in this regard, but `Bonsai.Sgen` will generate a nullable-T if the json-schema represents it using the `oneOf` keyword:
+
+```json
+ "pet": {
+ "oneOf": [
+ {"$ref": "#/definitions/Pet"},
+ {"type": "null"}
+ ]
+ }
+```
+
+For value types, the generated code will render a [Nullable value type](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types) type. This type will expose two properties: `HasValue` and `Value`, that can be used to test and manipulate the type, respectively.
+
+For reference types, the generated code will not render a nullable type since reference types are already nullable in C#. A consumer can test for `null` to determine if the value is present by simply using an `ExpressionTransform` operator with `it == null`.:
+
+:::workflow
+
+:::
+
+## Required fields
+
+`json-schema` supports the [`required`](https://json-schema.org/learn/getting-started-step-by-step#define-required-properties) keyword to specify which fields are required. By default, all fields are optional. This can be useful to enforce the presence of certain fields in the object at deserialization time. However, `Bonsai.Sgen` will not generate any code to enforce this requirement during object construction, only at deserialization. It is up to the user to ensure that the object is correctly populated before using it.
+
+> [!Note]
+> Some confusion maybe arise about the distinction between `null` and `required`. This is all the more confusing since different languages and libraries may refer to these concepts differently. For the sake of this tool (and honestly in general) the following definitions are used:
+
+> - `nullable` means that the field can be `null` or type `T`
+> - `required` means that the field must be present in the object at deserialization time
+> - An object can be `nullable` and `required` at the same time. This means it MUST be defined in the object, but it can be defined as `null`.
+> - An object can be `not required` and `nullable`. This does NOT mean that the object is, by default, `null`. It means that the object should have a default value, which can in theory be `null`.
+> - An object can be `not required` and `not nullable`. This means that the object must have a default value, which cannot be `null`.
+
+
+## Serialization and Deserialization
+
+One of the biggest perks of using json-schema to represent our objects is the guaranteed that all records are (de)serializable. This means that we can go from a text-based format (great specification and logging) to a `C#` type seamlessly, and vice-versa. `Bonsai.Sgen` will optionally generate (de)serialization operators for all objects in the schema if the `--serializer` property is not `None`. Currently, two formats are supported out of the box: `Json` (via [`NewtonsoftJson`](https://github.com/JamesNK/Newtonsoft.Json)) and `yaml` (via [`YamlDotNet`](https://github.com/aaubry/YamlDotNet)).
+
+The two operations are afforded via the `SerializeToYaml` (or `SerializeToJson`) and `DeserializeFromYaml` (or `DeserializeFromJson`) operators, respectively.
+
+`SerializeToYaml` will take a `T` object (known to the namespace) and return a `string` representation of the object.
+`DeserializeFromYaml` will take a `string` and return a `T` object. If validation fails, the operator will throw an exception.
+
+:::workflow
+
+:::
+
+> [!Tip]
+> Remember to add the necessary package references to your `Extensions.csproj` file depending on the serializer you want to use!
+> ```xml
+>
+>
+>
+>
+> ```
\ No newline at end of file
diff --git a/docs/articles/intro.md b/docs/articles/intro.md
new file mode 100644
index 0000000..1ee7386
--- /dev/null
+++ b/docs/articles/intro.md
@@ -0,0 +1,45 @@
+---
+uid: intro
+---
+
+## What is Bonsai.Sgen?
+
+`Bonsai.Sgen` is a code generator tool for the [Bonsai programming language](https://bonsai-rx.org/). It leverages [`json-schema`](https://json-schema.org/) as a standard to represent [record-like](https://en.wikipedia.org/wiki/Record_(computer_science)) structures, and automatically generates Bonsai-compatible isomorphic operators to create and manipulate these objects. It builds on top of the [`NJsonSchema` library](https://github.com/RicoSuter/NJsonSchema) by providing further customization of the generated code as well as bonsai-specific features.
+
+## Getting started
+
+1. Navigate to the [Bonsai.Sgen NuGet tool package](https://www.nuget.org/packages/Bonsai.Sgen/)
+2. Click `.NET CLI (Local)` and copy the two suggested commands. E.g.:
+
+ ```cmd
+ dotnet new tool-manifest # if you are setting up this repo
+ dotnet tool install --local Bonsai.Sgen
+ ```
+
+3. To view the tool help reference documentation, run:
+
+ ```cmd
+ dotnet bonsai.sgen --help
+ ```
+
+4. To generate YAML serialization classes from a schema file:
+
+ ```cmd
+ dotnet bonsai.sgen --schema schema.json --serializer YamlDotNet
+ ```
+
+5. To generate JSON serialization classes from a schema file:
+
+ ```cmd
+ dotnet bonsai.sgen --schema schema.json --serializer NewtonsoftJson
+ ```
+
+6. Copy the generated class file to your project `Extensions` folder.
+
+7. Add the necessary package references to your `Extensions.csproj` file. For example:
+
+ ```xml
+
+
+
+
\ No newline at end of file
diff --git a/docs/articles/why-bonsai-sgen.md b/docs/articles/why-bonsai-sgen.md
new file mode 100644
index 0000000..1fb2d7a
--- /dev/null
+++ b/docs/articles/why-bonsai-sgen.md
@@ -0,0 +1,70 @@
+---
+uid: why-bonsai-sgen
+---
+
+## Why should I care?
+
+`Bonsai.Sgen` attempts to solve the problem of writing boilerplate code to create represent data structures in Bonsai. Let's try to convince you by looking at a simple example.
+
+Let's we have a simple record-like object that represents a ´Person´:
+
+
+| Field Name | Type | Description |
+|------------|----------|---------------------------|
+| age | int | The age of a person |
+| first_name | string | The first name of the person |
+| last_name | string | The last name of the person |
+| dob | datetime | Date of birth |
+
+
+If we want to represent this object in Bonsai, we have a few alternatives:
+
+1. Using a `DynamicClass` object:
+
+:::workflow
+
+:::
+
+This approach is rather brittle as the representation of the record does not exist as a "first class citizen" and only at compile-time. This has a few implications one of which is the inability to create [Subject Sources](https://bonsai-rx.org/docs/articles/subjects.html#source-subjects) from the type.
+
+2. Modeling the object as a C# class using [Scripting Extensions](https://bonsai-rx.org/docs/articles/scripting-extensions.html):
+
+```Csharp
+public class Person
+{
+ public int Age;
+ public string FirstName;
+ public string LastName;
+ public DateTime DOB;
+}
+```
+
+This approach is more robust than the previous one, but it requires writing additional, boilerplate code to allow the creation of the object in Bonsai:
+
+```Csharp
+using Bonsai;
+using System;
+using System.Reactive.Linq;
+
+public class CreatePerson : Source
+{
+
+ public int Age { get; set; }
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public DateTime DOB { get; set; }
+
+ public override IObservable Generate()
+ {
+ return Observable.Return(new Person
+ {
+ Age = Age,
+ FirstName = FirstName,
+ LastName = LastName,
+ DOB = DOB
+ });
+ }
+}
+```
+
+As you can probably tell, neither of these approaches is ideal when it comes to scale large projects. This is where `Bonsai.Sgen` comes in.
\ No newline at end of file
diff --git a/docs/workflows/.gitignore b/docs/workflows/.gitignore
new file mode 100644
index 0000000..dfc8fe5
--- /dev/null
+++ b/docs/workflows/.gitignore
@@ -0,0 +1 @@
+*.bonsai.layout
\ No newline at end of file
diff --git a/docs/workflows/Extensions.csproj b/docs/workflows/Extensions.csproj
new file mode 100644
index 0000000..8d17170
--- /dev/null
+++ b/docs/workflows/Extensions.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net472
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/Extensions/CatExtensionMethods.cs b/docs/workflows/Extensions/CatExtensionMethods.cs
new file mode 100644
index 0000000..4fd051d
--- /dev/null
+++ b/docs/workflows/Extensions/CatExtensionMethods.cs
@@ -0,0 +1,14 @@
+
+namespace PersonAndDiscriminatedPets
+{
+ partial class Cat{
+ public static Cat operator +(Cat c1, Cat c2)
+ {
+ return new Cat
+ {
+ CanMeow = c1.CanMeow || c2.CanMeow,
+ Age = c1.Age + c2.Age
+ };
+ }
+ }
+}
diff --git a/docs/workflows/Extensions/CreatePerson.cs b/docs/workflows/Extensions/CreatePerson.cs
new file mode 100644
index 0000000..f0eb019
--- /dev/null
+++ b/docs/workflows/Extensions/CreatePerson.cs
@@ -0,0 +1,31 @@
+using Bonsai;
+using System;
+using System.Reactive.Linq;
+
+public class CreatePerson : Source
+{
+
+ public int Age { get; set; }
+ public string FirstName { get; set; }
+ public string LastName { get; set; }
+ public DateTime DOB { get; set; }
+
+ public override IObservable Generate()
+ {
+ return Observable.Return(new Person
+ {
+ Age = Age,
+ FirstName = FirstName,
+ LastName = LastName,
+ DOB = DOB
+ });
+ }
+}
+
+public class Person
+{
+ public int Age;
+ public string FirstName;
+ public string LastName;
+ public DateTime DOB;
+}
diff --git a/docs/workflows/Extensions/PersonAndDiscriminatedPets.cs b/docs/workflows/Extensions/PersonAndDiscriminatedPets.cs
new file mode 100644
index 0000000..a0bcd35
--- /dev/null
+++ b/docs/workflows/Extensions/PersonAndDiscriminatedPets.cs
@@ -0,0 +1,530 @@
+//----------------------
+//
+// Generated using the NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0) (http://NJsonSchema.org)
+//
+//----------------------
+
+
+namespace PersonAndDiscriminatedPets
+{
+ #pragma warning disable // Disable all warnings
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class Cat : Pet
+ {
+
+ private int _age;
+
+ private bool _canMeow = true;
+
+ public Cat()
+ {
+ }
+
+ protected Cat(Cat other) :
+ base(other)
+ {
+ _age = other._age;
+ _canMeow = other._canMeow;
+ }
+
+ [Newtonsoft.Json.JsonPropertyAttribute("age", Required=Newtonsoft.Json.Required.Always)]
+ public int Age
+ {
+ get
+ {
+ return _age;
+ }
+ set
+ {
+ _age = value;
+ }
+ }
+
+ [Newtonsoft.Json.JsonPropertyAttribute("can_meow")]
+ public bool CanMeow
+ {
+ get
+ {
+ return _canMeow;
+ }
+ set
+ {
+ _canMeow = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Cat(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new Cat(this));
+ }
+
+ protected override bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ if (base.PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(", ");
+ }
+ stringBuilder.Append("age = " + _age + ", ");
+ stringBuilder.Append("can_meow = " + _canMeow);
+ return true;
+ }
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class Dog : Pet
+ {
+
+ private int _age;
+
+ private bool _canBark = true;
+
+ public Dog()
+ {
+ }
+
+ protected Dog(Dog other) :
+ base(other)
+ {
+ _age = other._age;
+ _canBark = other._canBark;
+ }
+
+ [Newtonsoft.Json.JsonPropertyAttribute("age", Required=Newtonsoft.Json.Required.Always)]
+ public int Age
+ {
+ get
+ {
+ return _age;
+ }
+ set
+ {
+ _age = value;
+ }
+ }
+
+ [Newtonsoft.Json.JsonPropertyAttribute("can_bark")]
+ public bool CanBark
+ {
+ get
+ {
+ return _canBark;
+ }
+ set
+ {
+ _canBark = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Dog(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new Dog(this));
+ }
+
+ protected override bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ if (base.PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(", ");
+ }
+ stringBuilder.Append("age = " + _age + ", ");
+ stringBuilder.Append("can_bark = " + _canBark);
+ return true;
+ }
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
+ [Newtonsoft.Json.JsonConverter(typeof(JsonInheritanceConverter), "pet_type")]
+ [JsonInheritanceAttribute("dog", typeof(Dog))]
+ [JsonInheritanceAttribute("cat", typeof(Cat))]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class Pet
+ {
+
+ public Pet()
+ {
+ }
+
+ protected Pet(Pet other)
+ {
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Pet(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new Pet(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ return false;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class PersonAndPet
+ {
+
+ private string _owner;
+
+ private Pet _pet;
+
+ public PersonAndPet()
+ {
+ }
+
+ protected PersonAndPet(PersonAndPet other)
+ {
+ _owner = other._owner;
+ _pet = other._pet;
+ }
+
+ [Newtonsoft.Json.JsonPropertyAttribute("owner", Required=Newtonsoft.Json.Required.Always)]
+ public string Owner
+ {
+ get
+ {
+ return _owner;
+ }
+ set
+ {
+ _owner = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [Newtonsoft.Json.JsonPropertyAttribute("pet", Required=Newtonsoft.Json.Required.Always)]
+ public Pet Pet
+ {
+ get
+ {
+ return _pet;
+ }
+ set
+ {
+ _pet = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new PersonAndPet(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new PersonAndPet(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("owner = " + _owner + ", ");
+ stringBuilder.Append("pet = " + _pet);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.9.0.0 (Newtonsoft.Json v13.0.0.0)")]
+ [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface, AllowMultiple = true)]
+ internal class JsonInheritanceAttribute : System.Attribute
+ {
+ public JsonInheritanceAttribute(string key, System.Type type)
+ {
+ Key = key;
+ Type = type;
+ }
+
+ public string Key { get; private set; }
+
+ public System.Type Type { get; private set; }
+ }
+
+ [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.9.0.0 (Newtonsoft.Json v13.0.0.0)")]
+ public class JsonInheritanceConverter : Newtonsoft.Json.JsonConverter
+ {
+ internal static readonly string DefaultDiscriminatorName = "discriminator";
+
+ private readonly string _discriminatorName;
+
+ [System.ThreadStatic]
+ private static bool _isReading;
+
+ [System.ThreadStatic]
+ private static bool _isWriting;
+
+ public JsonInheritanceConverter()
+ {
+ _discriminatorName = DefaultDiscriminatorName;
+ }
+
+ public JsonInheritanceConverter(string discriminatorName)
+ {
+ _discriminatorName = discriminatorName;
+ }
+
+ public string DiscriminatorName { get { return _discriminatorName; } }
+
+ public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ try
+ {
+ _isWriting = true;
+
+ var jObject = Newtonsoft.Json.Linq.JObject.FromObject(value, serializer);
+ jObject.AddFirst(new Newtonsoft.Json.Linq.JProperty(_discriminatorName, GetSubtypeDiscriminator(value.GetType())));
+ writer.WriteToken(jObject.CreateReader());
+ }
+ finally
+ {
+ _isWriting = false;
+ }
+ }
+
+ public override bool CanWrite
+ {
+ get
+ {
+ if (_isWriting)
+ {
+ _isWriting = false;
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public override bool CanRead
+ {
+ get
+ {
+ if (_isReading)
+ {
+ _isReading = false;
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public override bool CanConvert(System.Type objectType)
+ {
+ return true;
+ }
+
+ public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
+ {
+ var jObject = serializer.Deserialize(reader);
+ if (jObject == null)
+ return null;
+
+ var discriminatorValue = jObject.GetValue(_discriminatorName);
+ var discriminator = discriminatorValue != null ? Newtonsoft.Json.Linq.Extensions.Value(discriminatorValue) : null;
+ var subtype = GetObjectSubtype(objectType, discriminator);
+
+ var objectContract = serializer.ContractResolver.ResolveContract(subtype) as Newtonsoft.Json.Serialization.JsonObjectContract;
+ if (objectContract == null || System.Linq.Enumerable.All(objectContract.Properties, p => p.PropertyName != _discriminatorName))
+ {
+ jObject.Remove(_discriminatorName);
+ }
+
+ try
+ {
+ _isReading = true;
+ return serializer.Deserialize(jObject.CreateReader(), subtype);
+ }
+ finally
+ {
+ _isReading = false;
+ }
+ }
+
+ private System.Type GetObjectSubtype(System.Type objectType, string discriminator)
+ {
+ foreach (var attribute in System.Reflection.CustomAttributeExtensions.GetCustomAttributes(System.Reflection.IntrospectionExtensions.GetTypeInfo(objectType), true))
+ {
+ if (attribute.Key == discriminator)
+ return attribute.Type;
+ }
+
+ return objectType;
+ }
+
+ private string GetSubtypeDiscriminator(System.Type objectType)
+ {
+ foreach (var attribute in System.Reflection.CustomAttributeExtensions.GetCustomAttributes(System.Reflection.IntrospectionExtensions.GetTypeInfo(objectType), true))
+ {
+ if (attribute.Type == objectType)
+ return attribute.Key;
+ }
+
+ return objectType.Name;
+ }
+ }
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
+ [System.ComponentModel.DefaultPropertyAttribute("Type")]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Combinator)]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ public partial class MatchPet : Bonsai.Expressions.SingleArgumentExpressionBuilder
+ {
+
+ public Bonsai.Expressions.TypeMapping Type { get; set; }
+
+ public override System.Linq.Expressions.Expression Build(System.Collections.Generic.IEnumerable arguments)
+ {
+ var typeMapping = Type;
+ var returnType = typeMapping != null ? typeMapping.GetType().GetGenericArguments()[0] : typeof(Pet);
+ return System.Linq.Expressions.Expression.Call(
+ typeof(MatchPet),
+ "Process",
+ new System.Type[] { returnType },
+ System.Linq.Enumerable.Single(arguments));
+ }
+
+
+ private static System.IObservable Process(System.IObservable source)
+ where TResult : Pet
+ {
+ return System.Reactive.Linq.Observable.Create(observer =>
+ {
+ var sourceObserver = System.Reactive.Observer.Create(
+ value =>
+ {
+ var match = value as TResult;
+ if (match != null) observer.OnNext(match);
+ },
+ observer.OnError,
+ observer.OnCompleted);
+ return System.ObservableExtensions.SubscribeSafe(source, sourceObserver);
+ });
+ }
+ }
+
+
+ ///
+ /// Serializes a sequence of data model objects into JSON strings.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Serializes a sequence of data model objects into JSON strings.")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ public partial class SerializeToJson
+ {
+
+ private System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, value => Newtonsoft.Json.JsonConvert.SerializeObject(value));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+ }
+
+
+ ///
+ /// Deserializes a sequence of JSON strings into data model objects.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.3.0.0 (Newtonsoft.Json v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Deserializes a sequence of JSON strings into data model objects.")]
+ [System.ComponentModel.DefaultPropertyAttribute("Type")]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ public partial class DeserializeFromJson : Bonsai.Expressions.SingleArgumentExpressionBuilder
+ {
+
+ public DeserializeFromJson()
+ {
+ Type = new Bonsai.Expressions.TypeMapping();
+ }
+
+ public Bonsai.Expressions.TypeMapping Type { get; set; }
+
+ public override System.Linq.Expressions.Expression Build(System.Collections.Generic.IEnumerable arguments)
+ {
+ var typeMapping = (Bonsai.Expressions.TypeMapping)Type;
+ var returnType = typeMapping.GetType().GetGenericArguments()[0];
+ return System.Linq.Expressions.Expression.Call(
+ typeof(DeserializeFromJson),
+ "Process",
+ new System.Type[] { returnType },
+ System.Linq.Enumerable.Single(arguments));
+ }
+
+ private static System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, value => Newtonsoft.Json.JsonConvert.DeserializeObject(value));
+ }
+ }
+}
diff --git a/docs/workflows/Extensions/PersonAndDogSgen.cs b/docs/workflows/Extensions/PersonAndDogSgen.cs
new file mode 100644
index 0000000..022b9a6
--- /dev/null
+++ b/docs/workflows/Extensions/PersonAndDogSgen.cs
@@ -0,0 +1,383 @@
+//----------------------
+//
+// Generated using the NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0) (http://NJsonSchema.org)
+//
+//----------------------
+
+
+namespace PersonAndDog
+{
+ #pragma warning disable // Disable all warnings
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class Person
+ {
+
+ private int _age;
+
+ private string _firstName;
+
+ private string _lastName;
+
+ private System.DateTimeOffset _dOB;
+
+ public Person()
+ {
+ }
+
+ protected Person(Person other)
+ {
+ _age = other._age;
+ _firstName = other._firstName;
+ _lastName = other._lastName;
+ _dOB = other._dOB;
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Age")]
+ public int Age
+ {
+ get
+ {
+ return _age;
+ }
+ set
+ {
+ _age = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="FirstName")]
+ public string FirstName
+ {
+ get
+ {
+ return _firstName;
+ }
+ set
+ {
+ _firstName = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="LastName")]
+ public string LastName
+ {
+ get
+ {
+ return _lastName;
+ }
+ set
+ {
+ _lastName = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="DOB")]
+ public System.DateTimeOffset DOB
+ {
+ get
+ {
+ return _dOB;
+ }
+ set
+ {
+ _dOB = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Person(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new Person(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("Age = " + _age + ", ");
+ stringBuilder.Append("FirstName = " + _firstName + ", ");
+ stringBuilder.Append("LastName = " + _lastName + ", ");
+ stringBuilder.Append("DOB = " + _dOB);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class Dog
+ {
+
+ private string _name;
+
+ private string _breed;
+
+ private int _age;
+
+ public Dog()
+ {
+ }
+
+ protected Dog(Dog other)
+ {
+ _name = other._name;
+ _breed = other._breed;
+ _age = other._age;
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Name")]
+ public string Name
+ {
+ get
+ {
+ return _name;
+ }
+ set
+ {
+ _name = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Breed")]
+ public string Breed
+ {
+ get
+ {
+ return _breed;
+ }
+ set
+ {
+ _breed = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Age")]
+ public int Age
+ {
+ get
+ {
+ return _age;
+ }
+ set
+ {
+ _age = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Dog(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new Dog(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("Name = " + _name + ", ");
+ stringBuilder.Append("Breed = " + _breed + ", ");
+ stringBuilder.Append("Age = " + _age);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class PersonAndPet
+ {
+
+ private Person _owner;
+
+ private Dog _pet;
+
+ public PersonAndPet()
+ {
+ }
+
+ protected PersonAndPet(PersonAndPet other)
+ {
+ _owner = other._owner;
+ _pet = other._pet;
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="owner")]
+ public Person Owner
+ {
+ get
+ {
+ return _owner;
+ }
+ set
+ {
+ _owner = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="pet")]
+ public Dog Pet
+ {
+ get
+ {
+ return _pet;
+ }
+ set
+ {
+ _pet = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new PersonAndPet(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new PersonAndPet(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("owner = " + _owner + ", ");
+ stringBuilder.Append("pet = " + _pet);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ ///
+ /// Serializes a sequence of data model objects into YAML strings.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Serializes a sequence of data model objects into YAML strings.")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ public partial class SerializeToYaml
+ {
+
+ private System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.SerializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value => serializer.Serialize(value));
+ });
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+ }
+
+
+ ///
+ /// Deserializes a sequence of YAML strings into data model objects.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Deserializes a sequence of YAML strings into data model objects.")]
+ [System.ComponentModel.DefaultPropertyAttribute("Type")]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ public partial class DeserializeFromYaml : Bonsai.Expressions.SingleArgumentExpressionBuilder
+ {
+
+ public DeserializeFromYaml()
+ {
+ Type = new Bonsai.Expressions.TypeMapping();
+ }
+
+ public Bonsai.Expressions.TypeMapping Type { get; set; }
+
+ public override System.Linq.Expressions.Expression Build(System.Collections.Generic.IEnumerable arguments)
+ {
+ var typeMapping = (Bonsai.Expressions.TypeMapping)Type;
+ var returnType = typeMapping.GetType().GetGenericArguments()[0];
+ return System.Linq.Expressions.Expression.Call(
+ typeof(DeserializeFromYaml),
+ "Process",
+ new System.Type[] { returnType },
+ System.Linq.Enumerable.Single(arguments));
+ }
+
+ private static System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.DeserializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value =>
+ {
+ var reader = new System.IO.StringReader(value);
+ var parser = new YamlDotNet.Core.MergingParser(new YamlDotNet.Core.Parser(reader));
+ return serializer.Deserialize(parser);
+ });
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/workflows/Extensions/PersonAndPetEnum.cs b/docs/workflows/Extensions/PersonAndPetEnum.cs
new file mode 100644
index 0000000..d1bac00
--- /dev/null
+++ b/docs/workflows/Extensions/PersonAndPetEnum.cs
@@ -0,0 +1,303 @@
+//----------------------
+//
+// Generated using the NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0) (http://NJsonSchema.org)
+//
+//----------------------
+
+
+namespace PersonAndPetEnum
+{
+ #pragma warning disable // Disable all warnings
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class Person
+ {
+
+ private int _age;
+
+ private string _firstName;
+
+ private string _lastName;
+
+ private System.DateTimeOffset _dOB;
+
+ public Person()
+ {
+ }
+
+ protected Person(Person other)
+ {
+ _age = other._age;
+ _firstName = other._firstName;
+ _lastName = other._lastName;
+ _dOB = other._dOB;
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Age")]
+ public int Age
+ {
+ get
+ {
+ return _age;
+ }
+ set
+ {
+ _age = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="FirstName")]
+ public string FirstName
+ {
+ get
+ {
+ return _firstName;
+ }
+ set
+ {
+ _firstName = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="LastName")]
+ public string LastName
+ {
+ get
+ {
+ return _lastName;
+ }
+ set
+ {
+ _lastName = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="DOB")]
+ public System.DateTimeOffset DOB
+ {
+ get
+ {
+ return _dOB;
+ }
+ set
+ {
+ _dOB = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Person(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new Person(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("Age = " + _age + ", ");
+ stringBuilder.Append("FirstName = " + _firstName + ", ");
+ stringBuilder.Append("LastName = " + _lastName + ", ");
+ stringBuilder.Append("DOB = " + _dOB);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ public enum Pet
+ {
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Dog")]
+ Dog = 0,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Cat")]
+ Cat = 1,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Fish")]
+ Fish = 2,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Bird")]
+ Bird = 3,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Reptile")]
+ Reptile = 4,
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class PersonAndPet
+ {
+
+ private Person _owner;
+
+ private Pet _pet;
+
+ public PersonAndPet()
+ {
+ }
+
+ protected PersonAndPet(PersonAndPet other)
+ {
+ _owner = other._owner;
+ _pet = other._pet;
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="owner")]
+ public Person Owner
+ {
+ get
+ {
+ return _owner;
+ }
+ set
+ {
+ _owner = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="pet")]
+ public Pet Pet
+ {
+ get
+ {
+ return _pet;
+ }
+ set
+ {
+ _pet = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new PersonAndPet(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new PersonAndPet(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("owner = " + _owner + ", ");
+ stringBuilder.Append("pet = " + _pet);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ ///
+ /// Serializes a sequence of data model objects into YAML strings.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Serializes a sequence of data model objects into YAML strings.")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ public partial class SerializeToYaml
+ {
+
+ private System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.SerializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value => serializer.Serialize(value));
+ });
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+ }
+
+
+ ///
+ /// Deserializes a sequence of YAML strings into data model objects.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Deserializes a sequence of YAML strings into data model objects.")]
+ [System.ComponentModel.DefaultPropertyAttribute("Type")]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ public partial class DeserializeFromYaml : Bonsai.Expressions.SingleArgumentExpressionBuilder
+ {
+
+ public DeserializeFromYaml()
+ {
+ Type = new Bonsai.Expressions.TypeMapping();
+ }
+
+ public Bonsai.Expressions.TypeMapping Type { get; set; }
+
+ public override System.Linq.Expressions.Expression Build(System.Collections.Generic.IEnumerable arguments)
+ {
+ var typeMapping = (Bonsai.Expressions.TypeMapping)Type;
+ var returnType = typeMapping.GetType().GetGenericArguments()[0];
+ return System.Linq.Expressions.Expression.Call(
+ typeof(DeserializeFromYaml),
+ "Process",
+ new System.Type[] { returnType },
+ System.Linq.Enumerable.Single(arguments));
+ }
+
+ private static System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.DeserializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value =>
+ {
+ var reader = new System.IO.StringReader(value);
+ var parser = new YamlDotNet.Core.MergingParser(new YamlDotNet.Core.Parser(reader));
+ return serializer.Deserialize(parser);
+ });
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/workflows/Extensions/PersonAndPetEnumNullable.cs b/docs/workflows/Extensions/PersonAndPetEnumNullable.cs
new file mode 100644
index 0000000..4d8f22c
--- /dev/null
+++ b/docs/workflows/Extensions/PersonAndPetEnumNullable.cs
@@ -0,0 +1,303 @@
+//----------------------
+//
+// Generated using the NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0) (http://NJsonSchema.org)
+//
+//----------------------
+
+
+namespace PersonAndPetEnumNullable
+{
+ #pragma warning disable // Disable all warnings
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class Person
+ {
+
+ private int _age;
+
+ private string _firstName;
+
+ private string _lastName;
+
+ private System.DateTimeOffset _dOB;
+
+ public Person()
+ {
+ }
+
+ protected Person(Person other)
+ {
+ _age = other._age;
+ _firstName = other._firstName;
+ _lastName = other._lastName;
+ _dOB = other._dOB;
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Age")]
+ public int Age
+ {
+ get
+ {
+ return _age;
+ }
+ set
+ {
+ _age = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="FirstName")]
+ public string FirstName
+ {
+ get
+ {
+ return _firstName;
+ }
+ set
+ {
+ _firstName = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="LastName")]
+ public string LastName
+ {
+ get
+ {
+ return _lastName;
+ }
+ set
+ {
+ _lastName = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="DOB")]
+ public System.DateTimeOffset DOB
+ {
+ get
+ {
+ return _dOB;
+ }
+ set
+ {
+ _dOB = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Person(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new Person(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("Age = " + _age + ", ");
+ stringBuilder.Append("FirstName = " + _firstName + ", ");
+ stringBuilder.Append("LastName = " + _lastName + ", ");
+ stringBuilder.Append("DOB = " + _dOB);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ public enum Pet
+ {
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Dog")]
+ Dog = 0,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Cat")]
+ Cat = 1,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Fish")]
+ Fish = 2,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Bird")]
+ Bird = 3,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Reptile")]
+ Reptile = 4,
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class PersonAndPet
+ {
+
+ private Person _owner;
+
+ private Pet? _pet;
+
+ public PersonAndPet()
+ {
+ }
+
+ protected PersonAndPet(PersonAndPet other)
+ {
+ _owner = other._owner;
+ _pet = other._pet;
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="owner")]
+ public Person Owner
+ {
+ get
+ {
+ return _owner;
+ }
+ set
+ {
+ _owner = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="pet")]
+ public Pet? Pet
+ {
+ get
+ {
+ return _pet;
+ }
+ set
+ {
+ _pet = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new PersonAndPet(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new PersonAndPet(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("owner = " + _owner + ", ");
+ stringBuilder.Append("pet = " + _pet);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ ///
+ /// Serializes a sequence of data model objects into YAML strings.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Serializes a sequence of data model objects into YAML strings.")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ public partial class SerializeToYaml
+ {
+
+ private System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.SerializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value => serializer.Serialize(value));
+ });
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+ }
+
+
+ ///
+ /// Deserializes a sequence of YAML strings into data model objects.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Deserializes a sequence of YAML strings into data model objects.")]
+ [System.ComponentModel.DefaultPropertyAttribute("Type")]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ public partial class DeserializeFromYaml : Bonsai.Expressions.SingleArgumentExpressionBuilder
+ {
+
+ public DeserializeFromYaml()
+ {
+ Type = new Bonsai.Expressions.TypeMapping();
+ }
+
+ public Bonsai.Expressions.TypeMapping Type { get; set; }
+
+ public override System.Linq.Expressions.Expression Build(System.Collections.Generic.IEnumerable arguments)
+ {
+ var typeMapping = (Bonsai.Expressions.TypeMapping)Type;
+ var returnType = typeMapping.GetType().GetGenericArguments()[0];
+ return System.Linq.Expressions.Expression.Call(
+ typeof(DeserializeFromYaml),
+ "Process",
+ new System.Type[] { returnType },
+ System.Linq.Enumerable.Single(arguments));
+ }
+
+ private static System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.DeserializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value =>
+ {
+ var reader = new System.IO.StringReader(value);
+ var parser = new YamlDotNet.Core.MergingParser(new YamlDotNet.Core.Parser(reader));
+ return serializer.Deserialize(parser);
+ });
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/workflows/Extensions/PersonAndPetsEnum.cs b/docs/workflows/Extensions/PersonAndPetsEnum.cs
new file mode 100644
index 0000000..518625b
--- /dev/null
+++ b/docs/workflows/Extensions/PersonAndPetsEnum.cs
@@ -0,0 +1,303 @@
+//----------------------
+//
+// Generated using the NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0) (http://NJsonSchema.org)
+//
+//----------------------
+
+
+namespace PersonAndPetsEnum
+{
+ #pragma warning disable // Disable all warnings
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class Person
+ {
+
+ private int _age;
+
+ private string _firstName;
+
+ private string _lastName;
+
+ private System.DateTimeOffset _dOB;
+
+ public Person()
+ {
+ }
+
+ protected Person(Person other)
+ {
+ _age = other._age;
+ _firstName = other._firstName;
+ _lastName = other._lastName;
+ _dOB = other._dOB;
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Age")]
+ public int Age
+ {
+ get
+ {
+ return _age;
+ }
+ set
+ {
+ _age = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="FirstName")]
+ public string FirstName
+ {
+ get
+ {
+ return _firstName;
+ }
+ set
+ {
+ _firstName = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="LastName")]
+ public string LastName
+ {
+ get
+ {
+ return _lastName;
+ }
+ set
+ {
+ _lastName = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="DOB")]
+ public System.DateTimeOffset DOB
+ {
+ get
+ {
+ return _dOB;
+ }
+ set
+ {
+ _dOB = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Person(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new Person(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("Age = " + _age + ", ");
+ stringBuilder.Append("FirstName = " + _firstName + ", ");
+ stringBuilder.Append("LastName = " + _lastName + ", ");
+ stringBuilder.Append("DOB = " + _dOB);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ public enum Pet
+ {
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Dog")]
+ Dog = 0,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Cat")]
+ Cat = 1,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Fish")]
+ Fish = 2,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Bird")]
+ Bird = 3,
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Reptile")]
+ Reptile = 4,
+ }
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class PersonAndPets
+ {
+
+ private Person _owner;
+
+ private System.Collections.Generic.List _pets = new System.Collections.Generic.List();
+
+ public PersonAndPets()
+ {
+ }
+
+ protected PersonAndPets(PersonAndPets other)
+ {
+ _owner = other._owner;
+ _pets = other._pets;
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="owner")]
+ public Person Owner
+ {
+ get
+ {
+ return _owner;
+ }
+ set
+ {
+ _owner = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="pets")]
+ public System.Collections.Generic.List Pets
+ {
+ get
+ {
+ return _pets;
+ }
+ set
+ {
+ _pets = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new PersonAndPets(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new PersonAndPets(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("owner = " + _owner + ", ");
+ stringBuilder.Append("pets = " + _pets);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ ///
+ /// Serializes a sequence of data model objects into YAML strings.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Serializes a sequence of data model objects into YAML strings.")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ public partial class SerializeToYaml
+ {
+
+ private System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.SerializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value => serializer.Serialize(value));
+ });
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+ }
+
+
+ ///
+ /// Deserializes a sequence of YAML strings into data model objects.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Deserializes a sequence of YAML strings into data model objects.")]
+ [System.ComponentModel.DefaultPropertyAttribute("Type")]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ public partial class DeserializeFromYaml : Bonsai.Expressions.SingleArgumentExpressionBuilder
+ {
+
+ public DeserializeFromYaml()
+ {
+ Type = new Bonsai.Expressions.TypeMapping();
+ }
+
+ public Bonsai.Expressions.TypeMapping Type { get; set; }
+
+ public override System.Linq.Expressions.Expression Build(System.Collections.Generic.IEnumerable arguments)
+ {
+ var typeMapping = (Bonsai.Expressions.TypeMapping)Type;
+ var returnType = typeMapping.GetType().GetGenericArguments()[0];
+ return System.Linq.Expressions.Expression.Call(
+ typeof(DeserializeFromYaml),
+ "Process",
+ new System.Type[] { returnType },
+ System.Linq.Enumerable.Single(arguments));
+ }
+
+ private static System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.DeserializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value =>
+ {
+ var reader = new System.IO.StringReader(value);
+ var parser = new YamlDotNet.Core.MergingParser(new YamlDotNet.Core.Parser(reader));
+ return serializer.Deserialize(parser);
+ });
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/workflows/Extensions/PersonSgen.cs b/docs/workflows/Extensions/PersonSgen.cs
new file mode 100644
index 0000000..add8fe9
--- /dev/null
+++ b/docs/workflows/Extensions/PersonSgen.cs
@@ -0,0 +1,196 @@
+//----------------------
+//
+// Generated using the NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0) (http://NJsonSchema.org)
+//
+//----------------------
+
+
+namespace DataSchema
+{
+ #pragma warning disable // Disable all warnings
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Source)]
+ public partial class Person
+ {
+
+ private int _age;
+
+ private string _firstName;
+
+ private string _lastName;
+
+ private System.DateTimeOffset _dOB;
+
+ public Person()
+ {
+ }
+
+ protected Person(Person other)
+ {
+ _age = other._age;
+ _firstName = other._firstName;
+ _lastName = other._lastName;
+ _dOB = other._dOB;
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="Age")]
+ public int Age
+ {
+ get
+ {
+ return _age;
+ }
+ set
+ {
+ _age = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="FirstName")]
+ public string FirstName
+ {
+ get
+ {
+ return _firstName;
+ }
+ set
+ {
+ _firstName = value;
+ }
+ }
+
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="LastName")]
+ public string LastName
+ {
+ get
+ {
+ return _lastName;
+ }
+ set
+ {
+ _lastName = value;
+ }
+ }
+
+ [System.Xml.Serialization.XmlIgnoreAttribute()]
+ [YamlDotNet.Serialization.YamlMemberAttribute(Alias="DOB")]
+ public System.DateTimeOffset DOB
+ {
+ get
+ {
+ return _dOB;
+ }
+ set
+ {
+ _dOB = value;
+ }
+ }
+
+ public System.IObservable Process()
+ {
+ return System.Reactive.Linq.Observable.Defer(() => System.Reactive.Linq.Observable.Return(new Person(this)));
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Select(source, _ => new Person(this));
+ }
+
+ protected virtual bool PrintMembers(System.Text.StringBuilder stringBuilder)
+ {
+ stringBuilder.Append("Age = " + _age + ", ");
+ stringBuilder.Append("FirstName = " + _firstName + ", ");
+ stringBuilder.Append("LastName = " + _lastName + ", ");
+ stringBuilder.Append("DOB = " + _dOB);
+ return true;
+ }
+
+ public override string ToString()
+ {
+ System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
+ stringBuilder.Append(GetType().Name);
+ stringBuilder.Append(" { ");
+ if (PrintMembers(stringBuilder))
+ {
+ stringBuilder.Append(" ");
+ }
+ stringBuilder.Append("}");
+ return stringBuilder.ToString();
+ }
+ }
+
+
+ ///
+ /// Serializes a sequence of data model objects into YAML strings.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Serializes a sequence of data model objects into YAML strings.")]
+ [Bonsai.CombinatorAttribute()]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ public partial class SerializeToYaml
+ {
+
+ private System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.SerializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value => serializer.Serialize(value));
+ });
+ }
+
+ public System.IObservable Process(System.IObservable source)
+ {
+ return Process(source);
+ }
+ }
+
+
+ ///
+ /// Deserializes a sequence of YAML strings into data model objects.
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Bonsai.Sgen", "0.4.0.0 (YamlDotNet v13.0.0.0)")]
+ [System.ComponentModel.DescriptionAttribute("Deserializes a sequence of YAML strings into data model objects.")]
+ [System.ComponentModel.DefaultPropertyAttribute("Type")]
+ [Bonsai.WorkflowElementCategoryAttribute(Bonsai.ElementCategory.Transform)]
+ [System.Xml.Serialization.XmlIncludeAttribute(typeof(Bonsai.Expressions.TypeMapping))]
+ public partial class DeserializeFromYaml : Bonsai.Expressions.SingleArgumentExpressionBuilder
+ {
+
+ public DeserializeFromYaml()
+ {
+ Type = new Bonsai.Expressions.TypeMapping();
+ }
+
+ public Bonsai.Expressions.TypeMapping Type { get; set; }
+
+ public override System.Linq.Expressions.Expression Build(System.Collections.Generic.IEnumerable arguments)
+ {
+ var typeMapping = (Bonsai.Expressions.TypeMapping)Type;
+ var returnType = typeMapping.GetType().GetGenericArguments()[0];
+ return System.Linq.Expressions.Expression.Call(
+ typeof(DeserializeFromYaml),
+ "Process",
+ new System.Type[] { returnType },
+ System.Linq.Enumerable.Single(arguments));
+ }
+
+ private static System.IObservable Process(System.IObservable source)
+ {
+ return System.Reactive.Linq.Observable.Defer(() =>
+ {
+ var serializer = new YamlDotNet.Serialization.DeserializerBuilder()
+ .Build();
+ return System.Reactive.Linq.Observable.Select(source, value =>
+ {
+ var reader = new System.IO.StringReader(value);
+ var parser = new YamlDotNet.Core.MergingParser(new YamlDotNet.Core.Parser(reader));
+ return serializer.Deserialize(parser);
+ });
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/workflows/person-and-discriminated-pets.json b/docs/workflows/person-and-discriminated-pets.json
new file mode 100644
index 0000000..73af29c
--- /dev/null
+++ b/docs/workflows/person-and-discriminated-pets.json
@@ -0,0 +1,84 @@
+{
+ "definitions": {
+ "Cat": {
+ "properties": {
+ "pet_type": {
+ "const": "cat",
+ "default": "cat",
+ "title": "Pet Type",
+ "type": "string"
+ },
+ "age": {
+ "title": "Age",
+ "type": "integer"
+ },
+ "can_meow": {
+ "default": true,
+ "title": "Can Meow",
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "age"
+ ],
+ "title": "Cat",
+ "type": "object"
+ },
+ "Dog": {
+ "properties": {
+ "pet_type": {
+ "const": "dog",
+ "default": "dog",
+ "title": "Pet Type",
+ "type": "string"
+ },
+ "age": {
+ "title": "Age",
+ "type": "integer"
+ },
+ "can_bark": {
+ "default": true,
+ "title": "Can Bark",
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "age"
+ ],
+ "title": "Dog",
+ "type": "object"
+ },
+ "Pet": {
+ "discriminator": {
+ "mapping": {
+ "cat": "#/definitions/Cat",
+ "dog": "#/definitions/Dog"
+ },
+ "propertyName": "pet_type"
+ },
+ "oneOf": [
+ {
+ "$ref": "#/definitions/Dog"
+ },
+ {
+ "$ref": "#/definitions/Cat"
+ }
+ ]
+ }
+ },
+ "properties": {
+ "owner": {
+ "title": "Owner",
+ "type": "string"
+ },
+ "pet": {
+ "$ref": "#/definitions/Pet"
+ }
+ },
+ "required": [
+ "owner",
+ "pet"
+ ],
+ "title": "PersonAndPet",
+ "type": "object"
+}
\ No newline at end of file
diff --git a/docs/workflows/person-and-dog.json b/docs/workflows/person-and-dog.json
new file mode 100644
index 0000000..6f343e8
--- /dev/null
+++ b/docs/workflows/person-and-dog.json
@@ -0,0 +1,48 @@
+{
+ "title": "PersonAndPet",
+ "definitions": {
+ "Person": {
+ "title": "Person",
+ "type": "object",
+ "properties": {
+ "Age": {
+ "type": "integer"
+ },
+ "FirstName": {
+ "type": "string"
+ },
+ "LastName": {
+ "type": "string"
+ },
+ "DOB": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
+ "Dog": {
+ "title": "Dog",
+ "type": "object",
+ "properties": {
+ "Name": {
+ "type": "string"
+ },
+ "Breed": {
+ "type": "string"
+ },
+ "Age": {
+ "type": "integer"
+ }
+ }
+ }
+ },
+ "type": "object",
+ "properties": {
+ "owner": {
+ "$ref": "#/definitions/Person"
+ },
+ "pet": {
+ "$ref": "#/definitions/Dog"
+ }
+ }
+}
diff --git a/docs/workflows/person-and-pet-enum-nullable.bonsai b/docs/workflows/person-and-pet-enum-nullable.bonsai
new file mode 100644
index 0000000..dda837d
--- /dev/null
+++ b/docs/workflows/person-and-pet-enum-nullable.bonsai
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+ Value Type
+
+
+
+ Pet
+
+
+ HasValue
+
+
+
+ Source1
+
+
+ HasValue
+
+
+
+
+
+
+
+
+
+
+ Value
+
+
+ Reference Type
+
+
+
+
+
+
+ Owner
+
+
+ IsNull
+ it == null
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/person-and-pet-enum-nullable.json b/docs/workflows/person-and-pet-enum-nullable.json
new file mode 100644
index 0000000..f8e7342
--- /dev/null
+++ b/docs/workflows/person-and-pet-enum-nullable.json
@@ -0,0 +1,41 @@
+{
+ "title": "PersonAndPet",
+ "definitions": {
+ "Person": {
+ "title": "Person",
+ "type": "object",
+ "properties": {
+ "Age": {
+ "type": "integer"
+ },
+ "FirstName": {
+ "type": "string"
+ },
+ "LastName": {
+ "type": "string"
+ },
+ "DOB": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
+ "Pet": {
+ "title": "Pet",
+ "type": "string",
+ "enum": ["Dog", "Cat", "Fish", "Bird", "Reptile"]
+ }
+ },
+ "type": "object",
+ "properties": {
+ "owner": {
+ "$ref": "#/definitions/Person"
+ },
+ "pet": {
+ "oneOf": [
+ {"$ref": "#/definitions/Pet"},
+ {"type": "null"}
+ ]
+ }
+ }
+}
diff --git a/docs/workflows/person-and-pet-enum.bonsai b/docs/workflows/person-and-pet-enum.bonsai
new file mode 100644
index 0000000..eb14530
--- /dev/null
+++ b/docs/workflows/person-and-pet-enum.bonsai
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/person-and-pet-enum.json b/docs/workflows/person-and-pet-enum.json
new file mode 100644
index 0000000..78234c0
--- /dev/null
+++ b/docs/workflows/person-and-pet-enum.json
@@ -0,0 +1,38 @@
+{
+ "title": "PersonAndPet",
+ "definitions": {
+ "Person": {
+ "title": "Person",
+ "type": "object",
+ "properties": {
+ "Age": {
+ "type": "integer"
+ },
+ "FirstName": {
+ "type": "string"
+ },
+ "LastName": {
+ "type": "string"
+ },
+ "DOB": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
+ "Pet": {
+ "title": "Pet",
+ "type": "string",
+ "enum": ["Dog", "Cat", "Fish", "Bird", "Reptile"]
+ }
+ },
+ "type": "object",
+ "properties": {
+ "owner": {
+ "$ref": "#/definitions/Person"
+ },
+ "pet": {
+ "$ref": "#/definitions/Pet"
+ }
+ }
+}
diff --git a/docs/workflows/person-and-pets-enum.bonsai b/docs/workflows/person-and-pets-enum.bonsai
new file mode 100644
index 0000000..7b9df4f
--- /dev/null
+++ b/docs/workflows/person-and-pets-enum.bonsai
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+ Owner
+
+
+ Pets
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/person-and-pets-enum.json b/docs/workflows/person-and-pets-enum.json
new file mode 100644
index 0000000..0f0f950
--- /dev/null
+++ b/docs/workflows/person-and-pets-enum.json
@@ -0,0 +1,41 @@
+{
+ "title": "PersonAndPets",
+ "definitions": {
+ "Person": {
+ "title": "Person",
+ "type": "object",
+ "properties": {
+ "Age": {
+ "type": "integer"
+ },
+ "FirstName": {
+ "type": "string"
+ },
+ "LastName": {
+ "type": "string"
+ },
+ "DOB": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
+ "Pet": {
+ "title": "Pet",
+ "type": "string",
+ "enum": ["Dog", "Cat", "Fish", "Bird", "Reptile"]
+ }
+ },
+ "type": "object",
+ "properties": {
+ "owner": {
+ "$ref": "#/definitions/Person"
+ },
+ "pets": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/Pet"
+ }
+ }
+ }
+}
diff --git a/docs/workflows/person-example-bonsai-sgen.bonsai b/docs/workflows/person-example-bonsai-sgen.bonsai
new file mode 100644
index 0000000..631776e
--- /dev/null
+++ b/docs/workflows/person-example-bonsai-sgen.bonsai
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/person-example-dynamic-class.bonsai b/docs/workflows/person-example-dynamic-class.bonsai
new file mode 100644
index 0000000..e6ddc50
--- /dev/null
+++ b/docs/workflows/person-example-dynamic-class.bonsai
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+ 0001-01-01T00:00:00
+
+
+
+
+
+
+ new(
+Item1 as Age,
+Item2 as FirstName,
+Item3 as LastName,
+Item4 as DOB
+)
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/person-pet-discriminated-union.bonsai b/docs/workflows/person-pet-discriminated-union.bonsai
new file mode 100644
index 0000000..453acb7
--- /dev/null
+++ b/docs/workflows/person-pet-discriminated-union.bonsai
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+ Pet
+
+
+
+
+
+ CanBark
+
+
+
+
+
+ CanMeow
+
+
+
+ 0
+ true
+
+
+
+
+
+ true
+ 0
+
+
+
+
+
+
+
+
+
+
+ CanBark
+
+
+
+
+
+ CanMeow
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/person.json b/docs/workflows/person.json
new file mode 100644
index 0000000..ce4f2c3
--- /dev/null
+++ b/docs/workflows/person.json
@@ -0,0 +1,19 @@
+{
+ "title": "Person",
+ "type": "object",
+ "properties": {
+ "Age": {
+ "type": "integer"
+ },
+ "FirstName": {
+ "type": "string"
+ },
+ "LastName": {
+ "type": "string"
+ },
+ "DOB": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+}
diff --git a/docs/workflows/personand-dog-example-bonsai-sgen.bonsai b/docs/workflows/personand-dog-example-bonsai-sgen.bonsai
new file mode 100644
index 0000000..62d3bcc
--- /dev/null
+++ b/docs/workflows/personand-dog-example-bonsai-sgen.bonsai
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ 0
+
+
+
+
+ 0
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/personand-dog-example-nested-building-bonsai-sgen.bonsai b/docs/workflows/personand-dog-example-nested-building-bonsai-sgen.bonsai
new file mode 100644
index 0000000..43236bc
--- /dev/null
+++ b/docs/workflows/personand-dog-example-nested-building-bonsai-sgen.bonsai
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+ Owner
+
+
+ Age
+
+
+ Pet
+
+
+ Breed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/serialization-example.bonsai b/docs/workflows/serialization-example.bonsai
new file mode 100644
index 0000000..a6285d5
--- /dev/null
+++ b/docs/workflows/serialization-example.bonsai
@@ -0,0 +1,48 @@
+
+
+
+
+
+ Serialization
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+
+
+
+ Deserialization
+
+
+
+
+
+
+
+
+
+ Pet.HasValue
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/workflows/sum-cats.bonsai b/docs/workflows/sum-cats.bonsai
new file mode 100644
index 0000000..0e3df9e
--- /dev/null
+++ b/docs/workflows/sum-cats.bonsai
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ 0
+ true
+
+
+
+
+ 0
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file