---
title: Deserialize Content Management API
slug: cms-12/api/deserialization
docTags: 
createdAt: 2026-08-07T16:45:42.000Z
---

When receiving a request, the Optimizely Content Management API first deserializes the data from the request body into models and then handles the request.

The Content Management API defines some input models (`ContentApiCreateModel`, `ContentApiPatchModel`), which plays a role as data transform objects for deserialization. Data is transformed into those models before being converted to `IContent` and saved to the database. For example, the diagram below illustrates the scenario of creating a content item.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/GPE4Gu0AfPRaGjDLu5pft-20260722-175700.jpg "deserialization.jpg")

The workflow follows the following steps:

- You request to Post a content endpoint with an input model in JSON format.
- The server accepts the request and transforms the JSON data into `ContentApiCreateModel`. Some metadata fields are mapped automatically, and the custom properties are converted to `PropertyModel`.
- Before saving the content, the `ContentApiCreateModel` is migrated to the `IContent`. The list of `PropertyModel` is converted to the `PropertyData`, then added to the `IContent.Property`.

The flow is the same for all endpoints.

## Customize the deserialization

If you define a custom `PropertyData` in your model, you need to register a custom `PropertyModel` and a custom converter to determine which `PropertyData` corresponds to which `PropertyModel`. For example, you have a custom property **PropertyStringList**, which inherits the `PropertyLongString`:

```csharp
[EditorHint(Global.SiteUIHints.Strings)]
[PropertyDefinitionTypePlugIn(Description = "A property for list of strings", DisplayName = "String List")]
public class PropertyStringList: PropertyLongString {
  protected String Separator = "\n";

  public String[] List {
    get {
      return (String[]) Value;
    }
  }

  public override Type PropertyValueType {
    get {
      return typeof (String[]);
    }
  }

  public override object SaveData(PropertyDataCollection properties) {
    return LongString;
  }

  public override object Value {
    get {
      var value = base.Value as string;

      if (value == null) {
        return null;
      }

      return value.Split(Separator.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
    }
    set {
      if (value is String[]) {
        var s = String.Join(Separator, value as String[]);
        base.Value = s;
      } else {
        base.Value = value;
      }
    }
  }
}
```

For Content Management API to handle this custom property, you need to register a corresponding `StringListPropertyModel`:

```csharp
public class StringListPropertyModel: PropertyModel<IList<string>, PropertyStringList> {
  [JsonConstructor]
  internal StringListPropertyModel(): this(new PropertyStringList()) {}

  public StringListPropertyModel(PropertyStringList propertyStringList): base(propertyStringList) {
    Value = propertyStringList.List;
  }
}
```

And a `StringListPropertyDataValueConverter` that implements the `IPropertyDataValueConverter`:

```csharp
[ServiceConfiguration(typeof (IPropertyDataValueConverter))]
[PropertyDataValueConverter(new Type[] {
  typeof (StringListPropertyModel)
})]
internal class StringListPropertyDataValueConverter: IPropertyDataValueConverter {
  ///<inheritdoc />
  public object Convert(IPropertyModel propertyModel, PropertyData propertyData) {
    if (propertyModel is null) {
      throw new ArgumentNullException(nameof(propertyModel));
    }

    return ((StringListPropertyModel) propertyModel).Value;
  }
}
```

## Data format

Flatten configuration controls whether the deserialized representation of properties should only include the value of all properties rather than both value and property type (for POST, PUT, or PATCH requests). This should be carefully noted because it impacts the data format sent to endpoints.

For information about the flattened model, see [Flatten](https://world.optimizely.com/documentation/developer-guides/content-management-api/getting-started/configuring-the-api/#Flatten).
