Search code examples
c#jsonasp.net-corejson-deserializationjson-serialization

How to do custom JSON serialization and deserialization in C#, when the object does not match the JSON


I have a class in the back-end of an asp.net application. This needs to be serialized to JSON and send to the front-end. This is no problem, except for the serialization. The class looks like this (class names and such are changed):

public class ClassA
{
  // There are some properties here that need to be serialized normally
  public string Name { get; set; }

  // This array needs custom serialization
  public ClassB[] Objects { get; set; }
}

With ClassB looking like this:

public class ClassB
{
  public EnumA SomeEnum { get; set; }
}

public enum EnumA{ A = 0, B = 1, C = 2 }

I need to serialize this to something like this:

{"name":"someName","objects":[2,1,1,0]}

Here the objects array should be filled with the numeral value of the someEnum property of ClassB.

So far I have this function that I added to ClassA, but I feel like this should be done differently:

public string ToJson()
        {
            string result = "{";
            result += "\"name\":\"" + Name + "\",";

            result += "\"objects\":[";
            for (int i = 0; i < Objects.Length; i++)
            {
                result += (int)Objects[i].SomeEnum;
                if (i < Objects.Length - 1)
                    result += ",";
            }
            result += "]}";

            return result;
        }

How do I go about this in a more nice way? I also need to deserialize the generated JSON back to a ClassA object. All help is appreciated.


Solution

  • You can use Newtonsoft JSON.

    First, add JsonProperty attributes to your classes:

    public class ClassA
    {
      [JsonProperty("name")]
      public string Name { get; set; }
    
      [JsonProperty("objects")]
      public ClassB[] Objects { get; set; }
    }
    

    Now create a ClassBConverter:

    public class ClassBConverter : JsonConverter<ClassB> {
        ...
    
        public override void WriteJson(JsonWriter writer, ClassB value, JsonSerializer serializer)
        {
            writer.WriteValue((int)value.SomeEnum);
        }
    
        public override ClassB ReadJson(JsonReader reader, Type objectType, ClassB existingValue, bool hasExistingValue, JsonSerializer serializer)
        {
            int i = (int)((long) reader.Value);
            return new ClassB { SomeEnum = i };
        }
    }
    

    And then do:

    JsonConvert.(De)SerializeObject<ClassA>(yourJSONString, new ClassBConverter());