runfastman
runfastman

Reputation: 947

JsonConverter call get base class json and add custom

I have a base and derived class and I want to customize the JSON serialization/deserialization of the derived class but build on what would be serialization/deserialization in the base class. I can't see how to do this with a JsonConverter class.

Example Classes

    public class MyBase
    {
        public long id { get; set; }
        public virtual string name { get; set; }
        public string desc { get; set; }
        ...
    }


    [JsonConverter(typeof(MyDerivedSerializer))]
    public class MyDerived : myBase
    {
        public double rate { get; set; }
        public double temp { get; set; }
        ...
    }

    public class MyDerivedSerializer : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
          var baseS = value as MyBase;
          //??? How to get JSON for base class

          //Add items for derived class
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            while ((reader.TokenType != JsonToken.Null) && (reader.TokenType != JsonToken.EndObject))
            {
              JObject jo = JObject.Load(reader);
              JToken itemProps = jo["properties"];
              jo.Remove("properties");
              foreach (JToken c in itemProps.Children())
              {
                if (c.Type == JTokenType.Property)
                {
                  JProperty p = c as JProperty;
                  if (!jo.ContainsKey(p.Name))
                    jo[p.Name] = p.Value;
                }
              }
            }
            //now that the JSON is good, how do I put the data in a created derived object
            var x = Activator.CreateInstance(objectType);
            return x;             
        }

        public override bool CanConvert(Type objectType)
        {
          return true;
        }
    }

The tool using the JSON needs all the derived class properties in a sub field called "properties" but I can't change my derived classes. So I would like to just edit the JSON using the JsonConveter to look like this.

    {
        "id": 33,
        "name": "xSource",
        "desc": "Main source",
        ...
        "properties": {
            "rate": "3.21",
            "temp": "245.2"
            ...
        }

    }

Upvotes: 1

Views: 1909

Answers (1)

Ryan Schlueter
Ryan Schlueter

Reputation: 2221

You will want to clean up a bit but I got this to spit out

{"id":1,"name":"Name","desc":"Desc","properties":{"rate":2.0,"temp":3.0}}

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JToken t = JToken.FromObject((MyBase)value);
        JObject jo = (JObject)t;

        var baseProperties = 
      typeof(MyBase).GetProperties(System.Reflection.BindingFlags.Public
       | System.Reflection.BindingFlags.Instance
       | System.Reflection.BindingFlags.DeclaredOnly);

        var derivedProperties = 
 typeof(MyDerived).GetProperties(System.Reflection.BindingFlags.Public
 | System.Reflection.BindingFlags.Instance
 | System.Reflection.BindingFlags.DeclaredOnly);

      var derivedValues =   jo.Properties().Where(x => derivedProperties.Any(y => y.Name == x.Name));
        var baseValues = jo.Properties().Where(x => baseProperties.Any(y => y.Name == x.Name)).ToList();
        JObject o = new JObject(baseValues);
        o.Add(new JProperty("properties", new JObject(derivedValues)));

        o.WriteTo(writer);

    }

Did have to remove the decorator from the class and move to the deseriliazation call like so was getting stackoverflow.

var result = JsonConvert.SerializeObject(test, new KeysJsonConverter());

Upvotes: 1

Related Questions