JSON
deserialization
.NET
C#
k__BackingField

How to remove k__BackingField from json when Deserialize

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The k__BackingField prefix appears in JSON output when serializing C# classes that use the [Serializable] attribute with a serializer that reads private fields instead of public properties. The compiler generates hidden backing fields like <Name>k__BackingField for auto-properties, and certain serializers expose them. The fix depends on which serializer you use: remove [Serializable], add [DataContract]/[DataMember] attributes, or configure the serializer to use property names.

Why It Happens

When you declare an auto-property in C#:

csharp
1[Serializable]
2public class User
3{
4    public string Name { get; set; }
5    public int Age { get; set; }
6}

The compiler generates hidden backing fields:

csharp
1// What the compiler actually creates:
2[Serializable]
3public class User
4{
5    [CompilerGenerated]
6    private string <Name>k__BackingField;
7
8    [CompilerGenerated]
9    private int <Age>k__BackingField;
10
11    public string Name
12    {
13        get => <Name>k__BackingField;
14        set => <Name>k__BackingField = value;
15    }
16}

When a serializer like BinaryFormatter or older JsonConvert settings reads fields (not properties), the JSON output looks like:

json
1{
2  "<Name>k__BackingField": "John",
3  "<Age>k__BackingField": 25
4}

Fix 1: Remove [Serializable] (Simplest)

If you are not using binary serialization, simply remove the [Serializable] attribute:

csharp
1// BEFORE — causes k__BackingField
2[Serializable]
3public class User
4{
5    public string Name { get; set; }
6    public int Age { get; set; }
7}
8
9// AFTER — clean JSON output
10public class User
11{
12    public string Name { get; set; }
13    public int Age { get; set; }
14}
csharp
var user = new User { Name = "John", Age = 25 };
var json = JsonSerializer.Serialize(user);
// {"Name":"John","Age":25}

Fix 2: Use [DataContract] and [DataMember]

If you need [Serializable] for other reasons, use [DataContract] to control JSON property names:

csharp
1using System.Runtime.Serialization;
2
3[Serializable]
4[DataContract]
5public class User
6{
7    [DataMember]
8    public string Name { get; set; }
9
10    [DataMember]
11    public int Age { get; set; }
12}

[DataContract] tells the serializer to use the property names (or custom names via [DataMember(Name = "...")]) instead of backing field names.

Fix 3: Newtonsoft.Json (Json.NET)

With Newtonsoft.Json, configure the contract resolver to ignore backing fields:

csharp
1using Newtonsoft.Json;
2using Newtonsoft.Json.Serialization;
3
4var settings = new JsonSerializerSettings
5{
6    ContractResolver = new DefaultContractResolver()
7};
8
9var json = JsonConvert.SerializeObject(user, settings);
10// {"Name":"John","Age":25}

Or use CamelCasePropertyNamesContractResolver for camelCase output:

csharp
1var settings = new JsonSerializerSettings
2{
3    ContractResolver = new CamelCasePropertyNamesContractResolver()
4};
5
6var json = JsonConvert.SerializeObject(user, settings);
7// {"name":"John","age":25}

You can also decorate properties with [JsonProperty]:

csharp
1[Serializable]
2public class User
3{
4    [JsonProperty("name")]
5    public string Name { get; set; }
6
7    [JsonProperty("age")]
8    public int Age { get; set; }
9}

Fix 4: System.Text.Json (.NET 6+)

System.Text.Json serializes public properties by default and does not expose backing fields:

csharp
1using System.Text.Json;
2
3[Serializable]
4public class User
5{
6    public string Name { get; set; }
7    public int Age { get; set; }
8}
9
10var user = new User { Name = "John", Age = 25 };
11var json = JsonSerializer.Serialize(user);
12// {"Name":"John","Age":25} — no k__BackingField
13
14// With camelCase naming
15var options = new JsonSerializerOptions
16{
17    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
18};
19json = JsonSerializer.Serialize(user, options);
20// {"name":"John","age":25}

System.Text.Json ignores fields by default. To include fields, you must explicitly opt in with JsonSerializerOptions.IncludeFields = true.

Fix 5: Custom Contract Resolver (Advanced)

If you need [Serializable] and cannot add [DataContract], create a custom resolver that filters out backing fields:

csharp
1using Newtonsoft.Json;
2using Newtonsoft.Json.Serialization;
3using System.Reflection;
4
5public class IgnoreBackingFieldResolver : DefaultContractResolver
6{
7    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
8    {
9        return base.GetSerializableMembers(objectType)
10            .Where(m => !m.Name.Contains("k__BackingField"))
11            .ToList();
12    }
13}
14
15var settings = new JsonSerializerSettings
16{
17    ContractResolver = new IgnoreBackingFieldResolver()
18};
19
20var json = JsonConvert.SerializeObject(user, settings);

Common Pitfalls

  • Assuming [Serializable] is needed for JSON: [Serializable] is for binary serialization (BinaryFormatter). JSON serializers like System.Text.Json and Newtonsoft.Json do not require it. Remove it unless you specifically need binary serialization.
  • Using BinaryFormatter for JSON: BinaryFormatter is insecure and deprecated in .NET 8+. If you see k__BackingField in your output, you may be using the wrong serializer entirely. Switch to System.Text.Json or Newtonsoft.Json.
  • Mixing [DataContract] and [JsonProperty]: If both attributes are present, the serializer may use one and ignore the other depending on configuration. Pick one approach and use it consistently across your model classes.
  • Forgetting [DataMember] on all properties: When [DataContract] is applied, only properties marked with [DataMember] are serialized. Unmarked properties are silently excluded from the output.
  • Deserialization fails with old JSON: If existing JSON contains k__BackingField keys and you fix the serialization, deserialization of the old data breaks. Map old field names during migration using [JsonProperty("<Name>k__BackingField")] temporarily.

Summary

  • k__BackingField appears when serializers read compiler-generated backing fields instead of public properties
  • The simplest fix is to remove [Serializable] if binary serialization is not needed
  • Use [DataContract]/[DataMember] to control serialized property names when [Serializable] is required
  • System.Text.Json ignores backing fields by default — it does not have this problem
  • Newtonsoft.Json with DefaultContractResolver also serializes properties correctly
  • Never use BinaryFormatter for JSON serialization — it is deprecated and insecure

Course illustration
Course illustration

All Rights Reserved.