🔄 Fractal Platform Transforms

Understanding data transformations between basic entities

0. Overview

What are Transforms?

Transforms allow you to convert data between different formats in Fractal Platform. Think of it like translating between languages - the same information can be expressed in different ways depending on what you need to do with it.

The Five Data Formats

Fractal Platform works with five basic data formats, each optimized for different tasks:

Format Description Best For
JSON Text representation of data APIs, configuration files, human-readable data exchange
Objects C# classes and objects Application logic, type-safe code, business rules
AttrList Flat list of attribute paths and values LINQ queries, attribute manipulation, granular control
Storage Database-level container for documents Persisting data, database operations, large datasets
Collection Storage with dimensions (metadata, validation, etc.) Forms, validation rules, complex data structures

Transform Flow

You can transform between any two formats. Here's how they connect:

JSON
Objects
AttrList
Storage
Collection

All formats are bidirectionally convertible

Common Transform Patterns

🔄 Pattern 1: API to Database

JSON (from API) → Objects (validate) → Storage (save to DB)

🔄 Pattern 2: Database to Form

Storage (from DB) → Collection (add validation) → Form Display

🔄 Pattern 3: Data Processing

Storage (from DB) → AttrList (LINQ operations) → Objects (business logic)

💡 Key Principle: Choose the format that makes your current task easiest. Don't worry about converting - Fractal Platform makes transforms simple and efficient.

Why Multiple Formats?

Each format has specific advantages:

  • JSON - Universal, works everywhere, human-readable
  • Objects - Type-safe, IntelliSense support, compile-time checking
  • AttrList - Granular control, powerful LINQ queries
  • Storage - Optimized for database, handles large datasets
  • Collection - Rich metadata, validation, multi-dimensional data
⚠️ Performance Note: While you can chain multiple transforms, consider performance for large datasets. Sometimes it's better to go directly from format A to format C rather than A → B → C.

1. Basic Entities

This document describes transformations between basic hierarchy entities in Fractal Platform. There are 5 basic entities that can describe a Document or list of Documents.

1.1 JSON

Text document that describes a hierarchy object.

{
  "Name": "Bob",
  "Age": 21,
  "IsManager": false
}

1.2 Objects

List of C# objects in the Application.

var objects = new[]
{
    new { Name = "Bob", Age = 21, IsManager = false },
    new { Name = "Tim", Age = 25, IsManager = true }
};

1.3 AttrList

List of attributes in the Document. Usually used when you want to do LINQ queries among Document attributes.

var docID = 1U;
var attrs = new AttrList
{
    new KeyValuePair<AttrPath, AttrValue>(new AttrPath("Name", docID),
                                        new AttrValue("Bob")),
    new KeyValuePair<AttrPath, AttrValue>(new AttrPath("Age", docID),
                                        new AttrValue(21)),
    new KeyValuePair<AttrPath, AttrValue>(new AttrPath("IsManager", docID),
                                        new AttrValue(false))
};
💡 Nested Attributes: Use backslash \ for nested objects and \[0] for arrays.
// JSON: {"Name":"Bob","Params":{"Age":21},"Arr":[1,2]}
var attrs = new AttrList
{
    new KeyValuePair(new AttrPath("Name", docID), new AttrValue("Bob")),
    new KeyValuePair(new AttrPath(@"Params\Age", docID), new AttrValue(21)),
    new KeyValuePair(new AttrPath(@"Arr\[0]", docID), new AttrValue(1)),
    new KeyValuePair(new AttrPath(@"Arr\[1]", docID), new AttrValue(2))
};

1.4 Storage

Container that contains list of Documents on Database level.

// Create standalone Storage
var storage = new BUFStorage("Document");
storage.Init();
// Read Storage from a Database
var storage = DocsOf("Users").ToStorage();

1.5 Collection

Container that contains list of Storages. Main Storage in the Collection is called Document. Other Storages around Document are called Dimension.

// Create standalone empty Collection
var collection = new Collection("MyCollection");
// Create collection based on a Storage
var storage = new BUFStorage("Document");
storage.Init();
var collection = new Collection(storage);
// Read collection from Database
var collection = DocsOf("Users").ToCollection();
💡 Fractal Structure: Each Dimension is based on a sub-Document and can have its own sub-Dimensions, forming a recursive fractal structure.

2. Transformations

2.1 JSON → Objects

Deserialize JSON to C# objects.

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
    public bool IsManager { get; set; }
}
var json = @"{
    'Name': 'Bob',
    'Age': 21,
    'IsManager': false
}";
var user = JsonConvert.DeserializeObject<User>(json);

2.2 JSON → AttrList

var json = @"{'Name': 'Bob','Age': 21,'IsManager': false}";
var attrs = AttrList.FromJson(Context.SystemContext, json);

2.3 JSON → Storage

var json = @"{'Name': 'Bob','Age': 21,'IsManager': false}";
var storage = new BUFStorage();
storage.Init();
storage.FromJson(Context.SystemContext, json, Constants.FIRST_DOC_ID);

2.4 JSON → Collection

var json = @"{'Name': 'Bob','Age': 21,'IsManager': false}";
var collection = Collection.FromJson(Context.SystemContext, json);

2.5 Objects → JSON

var user = new User
{
    Name = "Bob",
    Age = 21,
    IsManager = false
};
var json = user.ToJson();

2.6 Objects → AttrList

var user = new User { Name = "Bob", Age = 21, IsManager = false };
var attrs = user.ToAttrList(Context.SystemContext, Constants.FIRST_DOC_ID);

2.7 Objects → Storage

var user = new User { Name = "Bob", Age = 21, IsManager = false };
var storage = user.ToStorage(Context.SystemContext, Constants.FIRST_DOC_ID);

2.8 Objects → Collection

var user = new User { Name = "Bob", Age = 21, IsManager = false };
var collection = user.ToCollection(Context.SystemContext, Constants.FIRST_DOC_ID);

2.9 AttrList → JSON

var docID = 1U;
var attrs = new AttrList
{
    new KeyValuePair(new AttrPath("Name", docID), new AttrValue("Bob")),
    new KeyValuePair(new AttrPath("Age", docID), new AttrValue(21))
};
var json = attrs.ToJson(Context.SystemContext, Constants.FIRST_DOC_ID);

2.10 AttrList → Objects

var attrs = /* AttrList */;
var user = attrs.ToObject<User>();

2.11 AttrList → Storage

var attrs = /* AttrList */;
var storage = attrs.ToStorage();

2.12 AttrList → Collection

var attrs = /* AttrList */;
var collection = attrs.ToCollection();

2.13 Storage → JSON

var storage = new BUFStorage();
storage.Init();
var json = storage.ToJson(Context.SystemContext);

2.14 Storage → Objects

var storage = new BUFStorage();
storage.Init();
var users = storage.GetAll(Context.SystemContext)
                   .Select<User>();

2.15 Storage → AttrList

var storage = new BUFStorage();
storage.Init();
var attrs = storage.ToAttrList();

2.16 Storage → Collection

var storage = new BUFStorage();
storage.Init();
var collection = storage.ToCollection();

2.17 Collection → JSON

var collection = new Collection("Document");
var json = collection.ToJson(Context.SystemContext);

2.18 Collection → Objects

var collection = new Collection("Document");
var users = collection.GetAll(Context.SystemContext)
                      .Select<User>();

2.19 Collection → AttrList

var collection = new Collection("Document");
var attrs = collection.ToAttrList();

2.20 Collection → Storage

var collection = new Collection("Document");
var storage = collection.GetStorage(DimensionType.Document);

3. Practical Examples

Example 1: Open Form from JSON

// Open form based on Json
Collection.FromJson(context, "{'Name':'Bob','Age':21}")
          .OpenForm(context);

Example 2: Open Form with Validation

// Open form based on Json + set Dimension
Collection.FromJson(context, "{'Name':'Bob','Age':21}")
          .SetDimension(context,
                        DimensionType.Validation,
                        "{'Age':{'MinValue':18,'MaxValue':120}}")
          .OpenForm(context);

Example 3: Process Attributes with LINQ

// Open form based on Json + process attrs by LINQ
Collection.FromJson(context, "{'Arr':[1,2,3,4,5]}")
          .ToAttrList()
          .Skip(2) // skip 1,2 attributes
          .ToCollection(context)
          .OpenForm(context);

Example 4: Transform Database Data

// Open form based on Database + convert to attr list + update + open
DocsWhere("Numbers", new { Number = 3 })
      .ToCollection()
      .ToAttrList()
      .Select(x => new
      {
          Square = x.Value.GetUIntValue() * x.Value.GetUIntValue()
      }) // transform json from {'Number':3} to {'Square':9}
      .ToCollection(context)
      .OpenForm(context);

Example 5: Open Form from C# Object

// Open form based on C# object
var user = new
{
    Name = "Bob",
    Age = 21
};
user.ToCollection(context, Constants.FIRST_DOC_ID)
    .OpenForm(context);

Example 6: Open Form from Multiple Objects

// Open form based on C# objects
var users = new[]
{
    new
    {
        Name = "Bob",
        Age = 21
    },
    new
    {
        Name = "Tim",
        Age = 20
    }
};
users.ToCollection(context, Constants.FIRST_DOC_ID)
     .OpenForm(context);

Example 7: Filter Objects Before Opening Form

// Open form based on C# objects + filter
var users = new[]
{
    new
    {
        Name = "Bob",
        Age = 21
    },
    new
    {
        Name = "Tim",
        Age = 20
    }
};
users.ToCollection(context)
     .GetWhere(context, "{'Age':21}")
     .OpenForm();
💡 Pro Tip: These examples demonstrate the flexibility of Fractal Platform's transform system. You can chain multiple transformations to achieve complex data processing workflows while maintaining clean, readable code.

Best Practices

✅ When to Use Each Format

  • JSON - External APIs, configuration, logging
  • Objects - Business logic, calculations, type safety
  • AttrList - Complex queries, attribute-level operations
  • Storage - Database persistence, bulk operations
  • Collection - Forms, validation, multi-dimensional data
⚠️ Performance Considerations:
  • Avoid unnecessary transformations in tight loops
  • Cache transformed results when possible
  • Use Storage directly for large datasets
  • Consider memory usage when working with Collections