diff --git a/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/AttributesTest.cs b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/AttributesTest.cs
new file mode 100644
index 00000000000..26e252c70aa
--- /dev/null
+++ b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/AttributesTest.cs
@@ -0,0 +1,234 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using commercetools.Sdk.Api.Extensions;
+using commercetools.Sdk.Api.Models.Common;
+using commercetools.Sdk.Api.Models.Products;
+using commercetools.Sdk.Api.Models.ProductTypes;
+using commercetools.Sdk.Api.Serialization;
+using Microsoft.Extensions.DependencyInjection;
+using Xunit;
+
+namespace commercetools.Sdk.Api.Tests;
+
+public class AttributesTest
+{
+    [Fact]
+    public void attributes()
+    {
+        var s = new ServiceCollection();
+        s.UseCommercetoolsApiSerialization();
+        var p = s.BuildServiceProvider();
+
+        var projectResponse = File.ReadAllText("Resources/attributes.json");
+        var serializerService = p.GetService<IApiSerializerService>();
+
+        var variant = serializerService.Deserialize<ProductVariant>(projectResponse);
+
+        //assert
+        Assert.NotEmpty(variant.Attributes);
+        var attributes = variant.Attributes;
+        Assert.IsType<StringAttribute>(attributes.Get("text"));
+        Assert.Equal("foo", attributes.Get("text").ToStringAttribute().GetValue());
+        Assert.IsType<LocalizedStringAttribute>(attributes.Get("ltext"));
+        Assert.Equal("foo", attributes.Get("ltext").ToLocalizedStringAttribute().GetValue()["en"]);
+
+        Assert.IsType<PlainEnumAttribute>(attributes.Get("enum"));
+        Assert.Equal("foo", attributes.Get("enum").ToPlainEnumAttribute().GetValue().Label);
+        Assert.IsType<LocalizedEnumAttribute>(attributes.Get("lenum"));
+        Assert.Equal("foo", attributes.Get("lenum").ToLocalizedEnumAttribute().GetValue().Label["en"]);
+
+        Assert.IsType<StringAttribute>(attributes.Get("date"));
+        Assert.Equal("2020-01-01", attributes.Get("date").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("date-text"));
+        Assert.Equal("2020-01-01T", attributes.Get("date-text").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("time"));
+        Assert.Equal("13:15:00.123", attributes.Get("time").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("time-simple"));
+        Assert.Equal("13:15:00", attributes.Get("time-simple").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime"));
+        Assert.Equal("2020-01-01T13:15:00.123Z", attributes.Get("datetime").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime-simple"));
+        Assert.Equal("2020-01-01T13:15:00Z", attributes.Get("datetime-simple").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime-text"));
+        Assert.Equal("2018-09-24T00:00:00-0400", attributes.Get("datetime-text").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime-offset"));
+        Assert.Equal("2018-09-24T00:00:00-04:00", attributes.Get("datetime-offset").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime-no-offset"));
+        Assert.Equal("2018-09-24T00:00:00", attributes.Get("datetime-no-offset").ToStringAttribute().GetValue());
+
+        Assert.IsType<BooleanAttribute>(attributes.Get("boolean"));
+        Assert.True(attributes.Get("boolean").ToBooleanAttribute().GetValue());
+        Assert.IsType<LongAttribute>(attributes.Get("integer"));
+        Assert.Equal(10L, attributes.Get("integer").ToLongAttribute().GetValue());
+        Assert.Equal(10.0m, attributes.Get("integer").ToDecimalAttribute().GetValue());
+        Assert.IsType<DecimalAttribute>(attributes.Get("double"));
+        Assert.Equal(11.0m, attributes.Get("double").ToDecimalAttribute().GetValue());
+        Assert.Equal(11L, attributes.Get("double").ToLongAttribute().GetValue());
+
+        Assert.IsType<ReferenceAttribute>(attributes.Get("reference"));
+        Assert.Equal("12345", attributes.Get("reference").ToReferenceAttribute().GetValue().Id);
+        Assert.IsType<MoneyAttribute>(attributes.Get("money"));
+        Assert.Equal("EUR", attributes.Get("money").ToMoneyAttribute().GetValue().CurrencyCode);
+    }
+    
+    [Fact]
+    public void attributeSets()
+    {
+        var s = new ServiceCollection();
+        s.UseCommercetoolsApiSerialization();
+        var p = s.BuildServiceProvider();
+
+        var projectResponse = File.ReadAllText("Resources/attributes.json");
+        var serializerService = p.GetService<IApiSerializerService>();
+
+        var variant = serializerService.Deserialize<ProductVariant>(projectResponse);
+
+        //assert
+        Assert.NotEmpty(variant.Attributes);
+        var attributes = variant.Attributes;
+        Assert.IsType<SetAttribute<string>>(attributes.Get("set-text"));
+        Assert.Equal("foo", attributes.Get("set-text").ToSetStringAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<LocalizedString>>(attributes.Get("set-ltext"));
+        Assert.Equal("foo", attributes.Get("set-ltext").ToSetLocalizedStringAttribute().GetValue().First()["en"]);
+
+        Assert.IsType<SetAttribute<IAttributePlainEnumValue>>(attributes.Get("set-enum"));
+        Assert.Equal("foo", attributes.Get("set-enum").ToSetPlainEnumAttribute().GetValue().First().Label);
+        Assert.IsType<SetAttribute<IAttributeLocalizedEnumValue>>(attributes.Get("set-lenum"));
+        Assert.Equal("foo", attributes.Get("set-lenum").ToSetLocalizedEnumAttribute().GetValue().First().Label["en"]);
+
+        Assert.IsType<SetAttribute<string>>(attributes.Get("set-date"));
+        Assert.Equal("2020-01-01", attributes.Get("set-date").ToSetStringAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<string>>(attributes.Get("set-time"));
+        Assert.Equal("13:15:00.123", attributes.Get("set-time").ToSetStringAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<string>>(attributes.Get("set-datetime"));
+        Assert.Equal("2020-01-01T13:15:00.123Z", attributes.Get("set-datetime").ToSetStringAttribute().GetValue().First());
+
+        Assert.IsType<SetAttribute<bool>>(attributes.Get("set-boolean"));
+        Assert.True(attributes.Get("set-boolean").ToSetBooleanAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<long>>(attributes.Get("set-integer"));
+        Assert.Equal(10L, attributes.Get("set-integer").ToSetLongAttribute().GetValue().First());
+        Assert.Equal(10.0m, attributes.Get("set-integer").ToSetDecimalAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<decimal>>(attributes.Get("set-double"));
+        Assert.Equal(11.0m, attributes.Get("set-double").ToSetDecimalAttribute().GetValue().First());
+        Assert.Equal(11L, attributes.Get("set-double").ToSetLongAttribute().GetValue().First());
+
+        Assert.IsType<SetAttribute<IReference>>(attributes.Get("set-reference"));
+        Assert.Equal("12345", attributes.Get("set-reference").ToSetReferenceAttribute().GetValue().First().Id);
+        Assert.IsType<SetAttribute<ITypedMoney>>(attributes.Get("set-money"));
+        Assert.Equal("EUR", attributes.Get("set-money").ToSetMoneyAttribute().GetValue().First().CurrencyCode);
+    }
+
+    [Fact]
+    public void attributesAsDouble()
+    {
+        var s = new ServiceCollection();
+        s.UseCommercetoolsApiSerialization(new SerializationConfiguration()
+        {
+            DeserializeNumberAttributeAsDecimalOnly = true
+        });
+        var p = s.BuildServiceProvider();
+
+        var projectResponse = File.ReadAllText("Resources/attributes.json");
+        var serializerService = p.GetService<IApiSerializerService>();
+
+        var variant = serializerService.Deserialize<ProductVariant>(projectResponse);
+
+        //assert
+        Assert.NotEmpty(variant.Attributes);
+        var attributes = variant.Attributes;
+        Assert.IsType<StringAttribute>(attributes.Get("text"));
+        Assert.Equal("foo", attributes.Get("text").ToStringAttribute().GetValue());
+        Assert.IsType<LocalizedStringAttribute>(attributes.Get("ltext"));
+        Assert.Equal("foo", attributes.Get("ltext").ToLocalizedStringAttribute().GetValue()["en"]);
+
+        Assert.IsType<PlainEnumAttribute>(attributes.Get("enum"));
+        Assert.Equal("foo", attributes.Get("enum").ToPlainEnumAttribute().GetValue().Label);
+        Assert.IsType<LocalizedEnumAttribute>(attributes.Get("lenum"));
+        Assert.Equal("foo", attributes.Get("lenum").ToLocalizedEnumAttribute().GetValue().Label["en"]);
+
+        Assert.IsType<StringAttribute>(attributes.Get("date"));
+        Assert.Equal("2020-01-01", attributes.Get("date").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("date-text"));
+        Assert.Equal("2020-01-01T", attributes.Get("date-text").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("time"));
+        Assert.Equal("13:15:00.123", attributes.Get("time").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("time-simple"));
+        Assert.Equal("13:15:00", attributes.Get("time-simple").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime"));
+        Assert.Equal("2020-01-01T13:15:00.123Z", attributes.Get("datetime").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime-simple"));
+        Assert.Equal("2020-01-01T13:15:00Z", attributes.Get("datetime-simple").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime-text"));
+        Assert.Equal("2018-09-24T00:00:00-0400", attributes.Get("datetime-text").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime-offset"));
+        Assert.Equal("2018-09-24T00:00:00-04:00", attributes.Get("datetime-offset").ToStringAttribute().GetValue());
+        Assert.IsType<StringAttribute>(attributes.Get("datetime-no-offset"));
+        Assert.Equal("2018-09-24T00:00:00", attributes.Get("datetime-no-offset").ToStringAttribute().GetValue());
+
+        Assert.IsType<BooleanAttribute>(attributes.Get("boolean"));
+        Assert.True(attributes.Get("boolean").ToBooleanAttribute().GetValue());
+        Assert.IsType<DecimalAttribute>(attributes.Get("integer"));
+        Assert.Equal(10.0m, attributes.Get("integer").ToDecimalAttribute().GetValue());
+        Assert.Equal(10L, attributes.Get("integer").ToLongAttribute().GetValue());
+        Assert.IsType<DecimalAttribute>(attributes.Get("double"));
+        Assert.Equal(11.0m, attributes.Get("double").ToDecimalAttribute().GetValue());
+        Assert.Equal(11L, attributes.Get("double").ToLongAttribute().GetValue());
+
+        Assert.IsType<ReferenceAttribute>(attributes.Get("reference"));
+        Assert.Equal("12345", attributes.Get("reference").ToReferenceAttribute().GetValue().Id);
+        Assert.IsType<MoneyAttribute>(attributes.Get("money"));
+        Assert.Equal("EUR", attributes.Get("money").ToMoneyAttribute().GetValue().CurrencyCode);
+    }
+
+        [Fact]
+    public void attributeSetsAsDecimal()
+    {
+        var s = new ServiceCollection();
+        s.UseCommercetoolsApiSerialization(new SerializationConfiguration()
+        {
+            DeserializeNumberAttributeAsDecimalOnly = true
+        });
+        var p = s.BuildServiceProvider();
+
+        var projectResponse = File.ReadAllText("Resources/attributes.json");
+        var serializerService = p.GetService<IApiSerializerService>();
+
+        var variant = serializerService.Deserialize<ProductVariant>(projectResponse);
+
+        //assert
+        Assert.NotEmpty(variant.Attributes);
+        var attributes = variant.Attributes;
+        Assert.IsType<SetAttribute<string>>(attributes.Get("set-text"));
+        Assert.Equal("foo", attributes.Get("set-text").ToSetStringAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<LocalizedString>>(attributes.Get("set-ltext"));
+        Assert.Equal("foo", attributes.Get("set-ltext").ToSetLocalizedStringAttribute().GetValue().First()["en"]);
+
+        Assert.IsType<SetAttribute<IAttributePlainEnumValue>>(attributes.Get("set-enum"));
+        Assert.Equal("foo", attributes.Get("set-enum").ToSetPlainEnumAttribute().GetValue().First().Label);
+        Assert.IsType<SetAttribute<IAttributeLocalizedEnumValue>>(attributes.Get("set-lenum"));
+        Assert.Equal("foo", attributes.Get("set-lenum").ToSetLocalizedEnumAttribute().GetValue().First().Label["en"]);
+
+        Assert.IsType<SetAttribute<string>>(attributes.Get("set-date"));
+        Assert.Equal("2020-01-01", attributes.Get("set-date").ToSetStringAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<string>>(attributes.Get("set-time"));
+        Assert.Equal("13:15:00.123", attributes.Get("set-time").ToSetStringAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<string>>(attributes.Get("set-datetime"));
+        Assert.Equal("2020-01-01T13:15:00.123Z", attributes.Get("set-datetime").ToSetStringAttribute().GetValue().First());
+
+        Assert.IsType<SetAttribute<bool>>(attributes.Get("set-boolean"));
+        Assert.True(attributes.Get("set-boolean").ToSetBooleanAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<decimal>>(attributes.Get("set-integer"));
+        Assert.Equal(10m, attributes.Get("set-integer").ToSetDecimalAttribute().GetValue().First());
+        Assert.Equal(10L, attributes.Get("set-integer").ToSetLongAttribute().GetValue().First());
+        Assert.IsType<SetAttribute<decimal>>(attributes.Get("set-double"));
+        Assert.Equal(11.0m, attributes.Get("set-double").ToSetDecimalAttribute().GetValue().First());
+        Assert.Equal(11L, attributes.Get("set-double").ToSetLongAttribute().GetValue().First());
+
+        Assert.IsType<SetAttribute<IReference>>(attributes.Get("set-reference"));
+        Assert.Equal("12345", attributes.Get("set-reference").ToSetReferenceAttribute().GetValue().First().Id);
+        Assert.IsType<SetAttribute<ITypedMoney>>(attributes.Get("set-money"));
+        Assert.Equal("EUR", attributes.Get("set-money").ToSetMoneyAttribute().GetValue().First().CurrencyCode);
+    }
+}
\ No newline at end of file
diff --git a/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/CustomFieldsTest.cs b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/CustomFieldsTest.cs
new file mode 100644
index 00000000000..c00fc4e2d3f
--- /dev/null
+++ b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/CustomFieldsTest.cs
@@ -0,0 +1,124 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using commercetools.Sdk.Api.Models.Common;
+using commercetools.Sdk.Api.Models.Products;
+using commercetools.Sdk.Api.Models.ProductTypes;
+using commercetools.Sdk.Api.Models.Types;
+using commercetools.Sdk.Api.Serialization;
+using Microsoft.Extensions.DependencyInjection;
+using Xunit;
+
+namespace commercetools.Sdk.Api.Tests;
+
+public class CustomFieldsTest
+{
+    [Fact]
+    public void fields()
+    {
+        var s = new ServiceCollection();
+        s.UseCommercetoolsApiSerialization();
+        var p = s.BuildServiceProvider();
+
+        var projectResponse = File.ReadAllText("Resources/customfields.json");
+        var serializerService = p.GetService<IApiSerializerService>();
+
+        var custom = serializerService.Deserialize<ICustomFields>(projectResponse);
+
+        //assert
+        Assert.NotEmpty(custom.Fields);
+        var fields = custom.Fields;
+        Assert.IsType<string>(fields.AsString("text"));
+        Assert.Equal("foo", fields.AsString("text"));
+        Assert.IsType<LocalizedString>(fields.AsLocalizedString("ltext"));
+        Assert.Equal("foo", fields.AsLocalizedString("ltext")["en"]);
+
+        Assert.IsType<CustomFieldEnumValue>(fields.AsPlainEnum("enum"));
+        Assert.Equal("foo", fields.AsPlainEnum("enum").Label);
+        Assert.IsType<CustomFieldLocalizedEnumValue>(fields.AsLocalizedEnum("lenum"));
+        Assert.Equal("foo", fields.AsLocalizedEnum("lenum").Label["en"]);
+        
+        Assert.IsType<string>(fields.AsString("date"));
+        Assert.Equal("2020-01-01", fields.AsString("date"));
+        Assert.IsType<string>(fields.AsString("date-text"));
+        Assert.Equal("2020-01-01T", fields.AsString("date-text"));
+        Assert.IsType<string>(fields.AsString("time"));
+        Assert.Equal("13:15:00.123", fields.AsString("time"));
+        Assert.IsType<string>(fields.AsString("time-simple"));
+        Assert.Equal("13:15:00", fields.AsString("time-simple"));
+        Assert.IsType<string>(fields.AsString("datetime"));
+        Assert.Equal("2020-01-01T13:15:00.123Z", fields.AsString("datetime"));
+        Assert.IsType<string>(fields.AsString("datetime-simple"));
+        Assert.Equal("2020-01-01T13:15:00Z", fields.AsString("datetime-simple"));
+        Assert.IsType<string>(fields.AsString("datetime-text"));
+        Assert.Equal("2020-01-01T13:15:00-0400", fields.AsString("datetime-text"));
+        Assert.IsType<string>(fields.AsString("datetime-offset"));
+        Assert.Equal("2020-01-01T13:15:00-04:00", fields.AsString("datetime-offset"));
+        Assert.IsType<string>(fields.AsString("datetime-no-offset"));
+        Assert.Equal("2020-01-01T13:15:00", fields.AsString("datetime-no-offset"));
+
+        Assert.IsType<bool>(fields.AsBoolean("boolean"));
+        Assert.True(fields.AsBoolean("boolean"));
+        Assert.IsType<long>(fields.AsLong("integer"));
+        Assert.Equal(10L, fields.AsLong("integer"));
+        Assert.Equal(10.0m, fields.AsDecimal("integer"));
+        Assert.IsType<decimal>(fields.AsDecimal("double"));
+        Assert.Equal(11.0m, fields.AsDecimal("double"));
+        Assert.Equal(11L, fields.AsLong("double"));
+
+        Assert.IsType<ProductReference>(fields.AsReference("reference"));
+        Assert.Equal("12345",fields.AsReference("reference").Id);
+        Assert.IsType<TypedMoney>(fields.AsMoney("money"));
+        Assert.Equal("EUR", fields.AsMoney("money").CurrencyCode);
+        
+        Assert.Null(fields.AsLong("null"));
+        Assert.Null(fields.AsDecimal("null"));
+    }
+    
+        [Fact]
+    public void attributeSets()
+    {
+        var s = new ServiceCollection();
+        s.UseCommercetoolsApiSerialization();
+        var p = s.BuildServiceProvider();
+
+        var projectResponse = File.ReadAllText("Resources/customfields.json");
+        var serializerService = p.GetService<IApiSerializerService>();
+
+        var custom = serializerService.Deserialize<ICustomFields>(projectResponse);
+
+        //assert
+        Assert.NotEmpty(custom.Fields);
+        var fields = custom.Fields;
+        Assert.IsType<List<string>>(fields.AsSetString("set-text"));
+        Assert.Equal("foo", fields.AsSetString("set-text").First());
+        Assert.IsType<List<LocalizedString>>(fields.AsSetLocalizedString("set-ltext"));
+        Assert.Equal("foo", fields.AsSetLocalizedString("set-ltext").First()["en"]);
+
+        Assert.IsType<List<ICustomFieldEnumValue>>(fields.AsSetPlainEnum("set-enum"));
+        Assert.Equal("foo", fields.AsSetPlainEnum("set-enum").First().Label);
+        Assert.IsType<List<ICustomFieldLocalizedEnumValue>>(fields.AsSetLocalizedEnum("set-lenum"));
+        Assert.Equal("foo", fields.AsSetLocalizedEnum("set-lenum").First().Label["en"]);
+
+        Assert.IsType<List<string>>(fields.AsSetString("set-date"));
+        Assert.Equal("2020-01-01", fields.AsSetString("set-date").First());
+        Assert.IsType<List<string>>(fields.AsSetString("set-time"));
+        Assert.Equal("13:15:00.123", fields.AsSetString("set-time").First());
+        Assert.IsType<List<string>>(fields.AsSetString("set-datetime"));
+        Assert.Equal("2020-01-01T13:15:00.123Z", fields.AsSetString("set-datetime").First());
+
+        Assert.IsType<List<bool>>(fields.AsSetBoolean("set-boolean"));
+        Assert.True(fields.AsSetBoolean("set-boolean").First());
+        Assert.IsType<List<long>>(fields.AsSetLong("set-integer"));
+        Assert.Equal(10L, fields.AsSetLong("set-integer").First());
+        Assert.Equal(10.0m, fields.AsSetDecimal("set-integer").First());
+        Assert.IsType<List<decimal>>(fields.AsSetDecimal("set-double"));
+        Assert.Equal(11.0m, fields.AsSetDecimal("set-double").First());
+        Assert.Equal(11L, fields.AsSetLong("set-double").First());
+
+        Assert.IsType<List<IReference>>(fields.AsSetReference("set-reference"));
+        Assert.Equal("12345", fields.AsSetReference("set-reference").First().Id);
+        Assert.IsType<List<ITypedMoney>>(fields.AsSetMoney("set-money"));
+        Assert.Equal("EUR", fields.AsSetMoney("set-money").First().CurrencyCode);
+    }
+}
\ No newline at end of file
diff --git a/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/Resources/attributes.json b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/Resources/attributes.json
new file mode 100644
index 00000000000..49c17811c61
--- /dev/null
+++ b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/Resources/attributes.json
@@ -0,0 +1,214 @@
+{
+    "attributes": [
+        {
+            "name": "emptyArray",
+            "value": []
+        },
+        {
+            "name": "text",
+            "value": "foo"
+        },
+        {
+            "name": "ltext",
+            "value": { "en": "foo" }
+        },
+        {
+            "name": "integer",
+            "value": 10
+        },
+        {
+            "name": "double",
+            "value": 11.0
+        },
+        {
+            "name": "enum",
+            "value": {
+                "key": "foo",
+                "label": "foo"
+            }
+        },
+        {
+            "name": "lenum",
+            "value": {
+                "key": "foo",
+                "label": {
+                    "en": "foo"
+                }
+            }
+        },
+        {
+            "name": "money",
+            "value": {
+                "currencyCode": "EUR",
+                "centAmount": 100
+            }
+        },
+        {
+            "name": "reference",
+            "value": {
+                "typeId": "product",
+                "id": "12345"
+            }
+        },
+        {
+            "name": "date",
+            "value": "2020-01-01"
+        },
+        {
+            "name": "date-text",
+            "value": "2020-01-01T"
+        },
+        {
+            "name": "time",
+            "value": "13:15:00.123"
+        },
+        {
+            "name": "time-simple",
+            "value": "13:15:00"
+        },
+        {
+            "name": "datetime",
+            "value": "2020-01-01T13:15:00.123Z"
+        },
+        {
+            "name": "datetime-simple",
+            "value": "2020-01-01T13:15:00Z"
+        },
+        {
+            "name": "datetime-offset",
+            "value": "2018-09-24T00:00:00-04:00"
+        },
+        {
+            "name": "datetime-no-offset",
+            "value": "2018-09-24T00:00:00"
+        },
+        {
+            "name": "datetime-text",
+            "value": "2018-09-24T00:00:00-0400"
+        },
+        {
+            "name": "boolean",
+            "value": true
+        },
+        {
+            "name": "set-text",
+            "value": ["foo"]
+        },
+        {
+            "name": "set-ltext",
+            "value": [{ "en": "foo" }]
+        },
+        {
+            "name": "set-integer",
+            "value": [10]
+        },
+        {
+            "name": "set-double",
+            "value": [11.0]
+        },
+        {
+            "name": "set-enum",
+            "value": [{
+                "key": "foo",
+                "label": "foo"
+            }]
+        },
+        {
+            "name": "set-lenum",
+            "value": [{
+                "key": "foo",
+                "label": {
+                    "en": "foo"
+                }
+            }]
+        },
+        {
+            "name": "set-money",
+            "value": [{
+                "currencyCode": "EUR",
+                "centAmount": 100
+            }]
+        },
+        {
+            "name": "set-reference",
+            "value": [{
+                "typeId": "product",
+                "id": "12345"
+            }]
+        },
+        {
+            "name": "set-date",
+            "value": ["2020-01-01"]
+        },
+        {
+            "name": "set-datetime",
+            "value": ["2020-01-01T13:15:00.123Z"]
+        },
+        {
+            "name": "set-time",
+            "value": ["13:15:00.123"]
+        },
+        {
+            "name": "set-boolean",
+            "value": [true]
+        },
+        {
+            "name": "nested",
+            "value": [
+                {
+                    "name": "nested-string",
+                    "value": "foo"
+                },
+                {
+                    "name": "nested-enum",
+                    "value": {
+                        "key": "foo",
+                        "label": "foo"
+                    }
+                }
+            ]
+        },
+        {
+            "name": "set-nested",
+            "value": [
+                [
+                    {
+                        "name": "set-nested-string",
+                        "value": "foo"
+                    },
+                    {
+                        "name": "set-nested-enum",
+                        "value": {
+                            "key": "foo",
+                            "label": "foo"
+                        }
+                    }
+                ]
+            ]
+        },
+        {
+            "name": "set-empty",
+            "value": []
+        },
+        {
+            "name": "localizedNotes",
+            "value": [
+                {
+                    "de-DE": "Foo",
+                    "en": "Foo",
+                    "key": "FOO"
+                },
+                {
+                    "de-DE": "Bar",
+                    "en": "Bar",
+                    "key": "BAR"
+                },
+                {
+                    "de-DE": "Baz",
+                    "en": "Baz",
+                    "key": "BAZ"
+                }
+            ]
+        }
+    ]
+}
diff --git a/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/Resources/customfields.json b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/Resources/customfields.json
new file mode 100644
index 00000000000..f07cd0079de
--- /dev/null
+++ b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/Resources/customfields.json
@@ -0,0 +1,93 @@
+{
+    "fields": {
+        "text": "foo",
+        "ltext": {
+            "en": "foo"
+        },
+        "integer": 10,
+        "double": 11.0,
+        "enum": {
+            "key": "foo",
+            "label": "foo"
+        },
+        "lenum": {
+            "key": "foo",
+            "label": {
+                "en": "foo"
+            }
+        },
+        "money": {
+            "currencyCode": "EUR",
+            "centAmount": 100
+        },
+        "reference": {
+            "typeId": "product",
+            "id": "12345"
+        },
+        "null": null,
+        "date": "2020-01-01",
+        "date-text": "2020-01-01T",
+        "time": "13:15:00.123",
+        "time-simple": "13:15:00",
+        "datetime": "2020-01-01T13:15:00.123Z",
+        "datetime-zero": "2020-01-01T13:15:00.000Z",
+        "datetime-simple": "2020-01-01T13:15:00Z",
+        "datetime-offset": "2020-01-01T13:15:00-04:00",
+        "datetime-no-offset": "2020-01-01T13:15:00",
+        "datetime-text": "2020-01-01T13:15:00-0400",
+        "boolean": true,
+        "set-text": [
+            "foo"
+        ],
+        "set-ltext": [
+            {
+                "en": "foo"
+            }
+        ],
+        "set-integer": [
+            10
+        ],
+        "set-double": [
+            11.0
+        ],
+        "set-enum": [
+            {
+                "key": "foo",
+                "label": "foo"
+            }
+        ],
+        "set-lenum": [
+            {
+                "key": "foo",
+                "label": {
+                    "en": "foo"
+                }
+            }
+        ],
+        "set-money": [
+            {
+                "currencyCode": "EUR",
+                "centAmount": 100
+            }
+        ],
+        "set-reference": [
+            {
+                "typeId": "product",
+                "id": "12345"
+            }
+        ],
+        "set-date": [
+            "2020-01-01"
+        ],
+        "set-time": [
+            "13:15:00.123"
+        ],
+        "set-datetime": [
+            "2020-01-01T13:15:00.123Z"
+        ],
+        "set-boolean": [
+            true
+        ],
+        "set-empty": []
+    }
+}
diff --git a/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/commercetools.Sdk.Api.Tests.csproj b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/commercetools.Sdk.Api.Tests.csproj
index 85dffb90f09..d343fa479d2 100644
--- a/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/commercetools.Sdk.Api.Tests.csproj
+++ b/commercetools.Sdk/Tests/commercetools.Sdk.Api.Tests/commercetools.Sdk.Api.Tests.csproj
@@ -18,6 +18,12 @@
       <None Update="Resources\project.json">
         <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       </None>
+      <None Update="Resources\attributes.json">
+        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      </None>
+      <None Update="Resources\customfields.json">
+        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      </None>
       <None Update="appsettings.test.json">
         <CopyToOutputDirectory>Always</CopyToOutputDirectory>
       </None>
diff --git a/commercetools.Sdk/commercetools.Sdk.Api/DependencyInjectionSetup.cs b/commercetools.Sdk/commercetools.Sdk.Api/DependencyInjectionSetup.cs
index c641f4b624d..efee26fb2cc 100644
--- a/commercetools.Sdk/commercetools.Sdk.Api/DependencyInjectionSetup.cs
+++ b/commercetools.Sdk/commercetools.Sdk.Api/DependencyInjectionSetup.cs
@@ -72,9 +72,10 @@ public static void UseCommercetoolsApiSerialization(this IServiceCollection serv
             services.UseRegistration();
             services.UseSerialization();
             services.AddSingleton(serializationConfiguration ?? SerializationConfiguration.DefaultConfig);
-            services.AddSingleton<IMapperTypeRetriever<IFieldContainer>>(new FieldMapperTypeRetriever());
+            services.AddSingleton<IMapperTypeRetriever<IFieldContainer>>(provider => new FieldMapperTypeRetriever(provider.GetService<ISerializationConfiguration>()));
             services.AddSingleton<IMapperTypeRetriever<IAttribute>>(provider => new AttributeMapperTypeRetriever(provider.GetService<ISerializationConfiguration>()));
             services.AddSingleton<AttributeTypeRetriever>(provider => new AttributeTypeRetriever(provider.GetService<ISerializationConfiguration>()));
+            services.AddSingleton<FieldMapperTypeRetriever>(provider => new FieldMapperTypeRetriever(provider.GetService<ISerializationConfiguration>()));
             services.AddSingleton<SerializerService>();
             services.AddSingleton<IApiSerializerService, SerializerService>();
         }
diff --git a/commercetools.Sdk/commercetools.Sdk.Api/Generated/commercetoolsSdkApi/Models/Types/IFieldContainer.cs b/commercetools.Sdk/commercetools.Sdk.Api/Generated/commercetoolsSdkApi/Models/Types/IFieldContainer.cs
index 07e621faccb..0d9f10a263e 100644
--- a/commercetools.Sdk/commercetools.Sdk.Api/Generated/commercetoolsSdkApi/Models/Types/IFieldContainer.cs
+++ b/commercetools.Sdk/commercetools.Sdk.Api/Generated/commercetoolsSdkApi/Models/Types/IFieldContainer.cs
@@ -5,7 +5,7 @@
 namespace commercetools.Sdk.Api.Models.Types
 {
     [DeserializeAs(typeof(commercetools.Sdk.Api.Models.Types.FieldContainer))]
-    public interface IFieldContainer : IDictionary<string, Object>
+    public partial interface IFieldContainer : IDictionary<string, Object>
     {
     }
 }
diff --git a/commercetools.Sdk/commercetools.Sdk.Api/Models/Types/IFieldContainer.cs b/commercetools.Sdk/commercetools.Sdk.Api/Models/Types/IFieldContainer.cs
new file mode 100644
index 00000000000..30cd14c0c46
--- /dev/null
+++ b/commercetools.Sdk/commercetools.Sdk.Api/Models/Types/IFieldContainer.cs
@@ -0,0 +1,158 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using commercetools.Sdk.Api.Models.Common;
+
+namespace commercetools.Sdk.Api.Models.Types;
+
+public partial interface IFieldContainer
+{
+    public object GetValue(string fieldName)
+    {
+        TryGetValue(fieldName, out object value);
+        
+        return value;
+    }
+#nullable enable
+        CustomFieldEnumValue? AsPlainEnum(string fieldName)
+        {
+            if (GetValue(fieldName) is CustomFieldEnumValue value) { return value; }
+
+            return null;
+        }
+
+        public CustomFieldLocalizedEnumValue? AsLocalizedEnum(string fieldName)
+        {
+            if (GetValue(fieldName) is CustomFieldLocalizedEnumValue value) { return value; }
+
+            return null;
+        }
+
+        public LocalizedString? AsLocalizedString(string fieldName)
+        {
+            if (GetValue(fieldName) is LocalizedString value) { return value; }
+
+            return null;
+        }
+
+        public string? AsString(string fieldName)
+        {
+            if (GetValue(fieldName) is string value) { return value; }
+
+            return null;
+        }
+
+        public ITypedMoney? AsMoney(string fieldName)
+        {
+            if (GetValue(fieldName) is ITypedMoney value) { return value; }
+
+            return null;
+        }
+
+        public bool? AsBoolean(string fieldName)
+        {
+            if (GetValue(fieldName) is bool value) { return value; }
+
+            return null;
+        }
+
+        public decimal? AsDecimal(string fieldName)
+        {
+            var value = GetValue(fieldName);
+            if (GetValue(fieldName) is decimal decimalValue) { return decimalValue; }
+            if (GetValue(fieldName) is long longValue) { return Convert.ToDecimal(longValue); }
+
+            return null;
+        }
+
+        public long? AsLong(string fieldName)
+        {
+            var value = GetValue(fieldName);
+            if (value is decimal decimalValue) { return Convert.ToInt64(decimalValue); }
+            if (value is long longValue) { return longValue; }
+
+            return null;
+        }
+
+        public IReference? AsReference(string fieldName)
+        {
+            if (GetValue(fieldName) is IReference value) { return value; }
+
+            return null;
+        }
+
+        public IList<string>? AsSetString(string fieldName)
+        {
+            if (GetValue(fieldName) is IList<string> value) { return value; }
+        
+            return null;
+        }
+        
+        public IList<LocalizedString>? AsSetLocalizedString(string fieldName)
+        {
+            if (GetValue(fieldName) is IList<LocalizedString> value) { return value; }
+        
+            return null;
+        }
+        
+        public IList<ICustomFieldEnumValue>? AsSetPlainEnum(string fieldName)
+        {
+            if (GetValue(fieldName) is IList<ICustomFieldEnumValue> value) { return value; }
+        
+            return null;
+        }
+        
+        public IList<ICustomFieldLocalizedEnumValue>? AsSetLocalizedEnum(string fieldName)
+        {
+            if (GetValue(fieldName) is IList<ICustomFieldLocalizedEnumValue> value) { return value; }
+        
+            return null;
+        }
+        
+        public IList<ITypedMoney>? AsSetMoney(string fieldName)
+        {
+            if (GetValue(fieldName) is IList<ITypedMoney> value) { return value; }
+        
+            return null;
+        }
+        
+        public IList<bool>? AsSetBoolean(string fieldName)
+        {
+            if (GetValue(fieldName) is IList<bool> value) { return value; }
+        
+            return null;
+        }
+        
+        public IList<decimal>? AsSetDecimal(string fieldName)
+        {
+            var value = GetValue(fieldName);
+
+            if (value is IList<decimal> decimals) { return decimals; }
+            if (value is IList<long> longs)
+            {
+                return longs.Select(Convert.ToDecimal).ToList();
+            }
+
+            return null;
+        }
+        
+        public IList<long>? AsSetLong(string fieldName)
+        {
+            var value = GetValue(fieldName);
+            if (value is IList<long> longs) { return longs; }
+            if (value is IList<decimal> decimals)
+            {
+                return decimals.Select(Convert.ToInt64).ToList();
+            }
+
+            return null;
+        }
+        
+        public IList<IReference>? AsSetReference(string fieldName)
+        {
+            if (GetValue(fieldName) is IList<IReference> value) { return value; }
+        
+            return null;
+        }
+#nullable disable
+}
\ No newline at end of file
diff --git a/commercetools.Sdk/commercetools.Sdk.Api/Serialization/ISerializationConfiguration.cs b/commercetools.Sdk/commercetools.Sdk.Api/Serialization/ISerializationConfiguration.cs
index 2fad3575f32..9d4ac5b5fbc 100644
--- a/commercetools.Sdk/commercetools.Sdk.Api/Serialization/ISerializationConfiguration.cs
+++ b/commercetools.Sdk/commercetools.Sdk.Api/Serialization/ISerializationConfiguration.cs
@@ -7,6 +7,8 @@ public interface ISerializationConfiguration
     {
         bool DeserializeNumberAttributeAsDecimalOnly { get; set; }
 
+        bool DeserializeNumberCustomFieldAsDecimalOnly { get; set; }
+
         Dictionary<string, Type> AttributeTypeMap { get; set; }
     }
 }
\ No newline at end of file
diff --git a/commercetools.Sdk/commercetools.Sdk.Api/Serialization/MapperTypeRetrievers/FieldMapperTypeRetriever.cs b/commercetools.Sdk/commercetools.Sdk.Api/Serialization/MapperTypeRetrievers/FieldMapperTypeRetriever.cs
index e6af6455a79..438c58db1d2 100644
--- a/commercetools.Sdk/commercetools.Sdk.Api/Serialization/MapperTypeRetrievers/FieldMapperTypeRetriever.cs
+++ b/commercetools.Sdk/commercetools.Sdk.Api/Serialization/MapperTypeRetrievers/FieldMapperTypeRetriever.cs
@@ -11,8 +11,10 @@ namespace commercetools.Sdk.Api.Serialization.MapperTypeRetrievers
 {
     public class FieldMapperTypeRetriever : MapperTypeRetriever<IFieldContainer>
     {
-        public FieldMapperTypeRetriever()
+        private readonly ISerializationConfiguration _serializationConfiguration;
+        public FieldMapperTypeRetriever(ISerializationConfiguration serializationConfiguration = null)
         {
+            this._serializationConfiguration = serializationConfiguration ?? SerializationConfiguration.DefaultConfig;
         }
 
         [Obsolete("use constructor without cultureValidator")]
@@ -31,7 +33,15 @@ public override Type GetTypeForToken(JsonElement element)
                     tokenType = typeof(bool);
                     break;
                 case JsonValueKind.Number:
-                    tokenType = element.IsLongOrInt() ? typeof(long) : typeof(decimal);
+                    if (_serializationConfiguration.DeserializeNumberCustomFieldAsDecimalOnly)
+                    {
+                        tokenType = typeof(decimal);
+                    }
+                    else
+                    {
+                        tokenType = element.IsLongOrInt() ? typeof(long) : typeof(decimal);
+                    }
+
                     break;
                 case JsonValueKind.String:
                     tokenType = typeof(string);
@@ -41,7 +51,11 @@ public override Type GetTypeForToken(JsonElement element)
                     tokenType = typeof(object);
                     break;
                 case JsonValueKind.Object:
-                    if (element.IsMoneyElement())
+                    if (element.IsEnumElement())
+                        tokenType = typeof(ICustomFieldEnumValue);
+                    else if (element.IsLocalizedEnumElement())
+                        tokenType = typeof(ICustomFieldLocalizedEnumValue);
+                    else if (element.IsMoneyElement())
                         tokenType = typeof(ITypedMoney);
                     else if (element.IsReferenceElement())
                         tokenType = typeof(IReference);
diff --git a/commercetools.Sdk/commercetools.Sdk.Api/Serialization/SerializationConfiguration.cs b/commercetools.Sdk/commercetools.Sdk.Api/Serialization/SerializationConfiguration.cs
index 9872d2efd3e..0490efd3129 100644
--- a/commercetools.Sdk/commercetools.Sdk.Api/Serialization/SerializationConfiguration.cs
+++ b/commercetools.Sdk/commercetools.Sdk.Api/Serialization/SerializationConfiguration.cs
@@ -7,6 +7,7 @@ public class SerializationConfiguration : ISerializationConfiguration
     {
         public static readonly ISerializationConfiguration DefaultConfig = new SerializationConfiguration();
         public bool DeserializeNumberAttributeAsDecimalOnly { get; set; } = false;
+        public bool DeserializeNumberCustomFieldAsDecimalOnly { get; set; } = false;
 
         public Dictionary<string, Type> AttributeTypeMap { get; set; } = new Dictionary<string, Type>();
     }