Migwell
Migwell

Reputation: 20137

How do you modify the Json serialization of just one field using Json.net?

Say for example I'm trying to convert an object with 10 fields to Json, however I need to modify the process of serializing 1 of these fields. At the moment, I'd have to use manually write out each property like this:

 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteStartObject();

        writer.WritePropertyName("Field1");
        serializer.Serialize(writer, value.Field1);

        writer.WritePropertyName("Field2");
        serializer.Serialize(writer, value.Field2);

        writer.WritePropertyName("Field3");
        serializer.Serialize(writer, value.Field3);

        writer.WritePropertyName("Field4");
        serializer.Serialize(writer, Convert.ToInt32(value.Field4)); //Modifying one field here

        //Six more times

        writer.WriteEndObject();
    }

This isn't good code, and it's really irritating to have to write. Is there any way of getting Json.net to serialize all but one property automatically? Or possibly generate a JObject automatically and modify that?

Upvotes: 2

Views: 7426

Answers (3)

vutran
vutran

Reputation: 404

You might use System.Reflection, however it's slow but you don't have to modify the class

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    writer.WriteStartObject();

    Type vType = value.GetType();
    MemberInfo[] properties = vType.GetProperties(BindingFlags.Public
                                        | BindingFlags.Instance);

    foreach (PropertyInfo property in properties)
    {
        object serValue = null;
        if (property.Name == "Field4")
        {
            serValue = Convert.ToInt32(property.GetValue(value, null));
        }
        else
        {
            serValue = property.GetValue(value, null);
        }
        writer.WritePropertyName(property.Name);
        serializer.Serialize(writer, serValue);
    }

    writer.WriteEndObject();
}

Upvotes: 1

IronGeek
IronGeek

Reputation: 4883

You can try by decorating the property you need to modify manually with JsonConverterAttribute and pass the appropriate JsonConverter type.

For example, using OP's original example:

public class IntegerConverter : JsonConverter
{
  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  {
    serializer.Serialize(writer, Convert.ToInt32(value));
  }

  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  {
    throw new NotImplementedException();
  }

  public override bool CanConvert(Type objectType)
  {
    return objectType == typeof(string);
  }
}

class TestJson
{
  public string Field1 { get; set; }
  public string Field2 { get; set; }
  public string Field3 { get; set; }

  [JsonConverter(typeof(IntegerConverter))]
  public string Field4 { get; set; }        
}

You can then serialize the object as usual using JsonConvert:

var test = new TestJson {Field1 = "1", Field2 = "2", Field3 = "3", Field4 = "4"};

var jsonString = JsonConvert.SerializeObject(test);

Upvotes: 4

Kenneth
Kenneth

Reputation: 28737

If you have access to the class (and you always need it to be serialized the same way) you could modify the class to your needs. Suppose this.is the class:

public class MyClass
{
    public string Value4 {get; set;}
}

If you want value 4 to be serialized as an int you could do this:

public class MyClass
{
    [JsonIgnore()]
    public string Value4 {get; set;}

    public int Value4AsInt
    {
        return Convert.ToInt32(Value4);
    }
}

Upvotes: 1

Related Questions