In order to serialize your wrapper class such that its internal dictionary appears in the JSON as if the wrapper were not there, you need a custom JsonConverter. A JsonConverter gives you direct control over what gets serialized and/or deserialized for a particular class.
Below is a converter that should work for your case. Since you didn't really provide any details about your wrapper class other than it has a field called values to hold the dictionary, I used reflection to gain access to it. If your class has public methods to manipulate the dictionary directly, you can change the converter to use those methods instead, if you prefer. Here is the code:
class DictionaryWrapperConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == typeof(MyWrapper)); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { MyWrapper wrapper = (MyWrapper)value; FieldInfo field = typeof(MyWrapper).GetField("values", BindingFlags.NonPublic | BindingFlags.Instance); JObject jo = JObject.FromObject(field.GetValue(wrapper)); jo.WriteTo(writer); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject jo = JObject.Load(reader); MyWrapper wrapper = new MyWrapper(); FieldInfo field = typeof(MyWrapper).GetField("values", BindingFlags.NonPublic | BindingFlags.Instance); field.SetValue(wrapper, jo.ToObject(field.FieldType)); return wrapper; } }
To tie the custom converter to your wrapper class, you can add a [JsonConverter] attribute to the class definition:
[JsonConverter(typeof(DictionaryWrapperConverter))] class MyWrapper : IEnumerable { Dictionary<string, string> values = new Dictionary<string, string>(); public void Add(string key, string value) { values.Add(key, value); } IEnumerator IEnumerable.GetEnumerator() { return values.GetEnumerator(); } }
Here is a full demo showing the converter in action, first serializing and deserializing a single instance of the wrapper class, then serializing and deserializing a list of wrappers:
class Program { static void Main(string[] args) { MyWrapper wrapper = new MyWrapper(); wrapper.Add("foo", "bar"); wrapper.Add("fizz", "bang"); // serialize single wrapper instance string json = JsonConvert.SerializeObject(wrapper, Formatting.Indented); Console.WriteLine(json); Console.WriteLine(); // deserialize single wrapper instance wrapper = JsonConvert.DeserializeObject<MyWrapper>(json); foreach (KeyValuePair<string, string> kvp in wrapper) { Console.WriteLine(kvp.Key + "=" + kvp.Value); } Console.WriteLine(); Console.WriteLine("----------\n"); MyWrapper wrapper2 = new MyWrapper(); wrapper2.Add("a", "1"); wrapper2.Add("b", "2"); wrapper2.Add("c", "3"); List<MyWrapper> list = new List<MyWrapper> { wrapper, wrapper2 }; // serialize list of wrappers json = JsonConvert.SerializeObject(list, Formatting.Indented); Console.WriteLine(json); Console.WriteLine(); // deserialize list of wrappers list = JsonConvert.DeserializeObject<List<MyWrapper>>(json); foreach (MyWrapper w in list) { foreach (KeyValuePair<string, string> kvp in w) { Console.WriteLine(kvp.Key + "=" + kvp.Value); } Console.WriteLine(); } } }
Output:
{ "foo": "bar", "fizz": "bang" } foo=bar fizz=bang ---------- [ { "foo": "bar", "fizz": "bang" }, { "a": "1", "b": "2", "c": "3" } ] foo=bar fizz=bang a=1 b=2 c=3
JsonConvert.SerializeObjecton the array, prior to callingToJson(). The nett result will be the same.[JsonProperty]attribute. That is why you need the converter.