Skip to content

Instantly share code, notes, and snippets.

@mjul
Created December 20, 2018 09:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjul/74a12286c129476c0c5bf175ecf38de1 to your computer and use it in GitHub Desktop.
Save mjul/74a12286c129476c0c5bf175ecf38de1 to your computer and use it in GitHub Desktop.
Using JsonConverter<T> with NewtonSoft Json to serialize a class as an object where the keys and values are defined dynamically in a dictionary member of the class
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xunit;
using Xunit.Abstractions;
namespace JsonNetSerialization
{
[JsonObject(ItemConverterType = typeof(NotQuiteADictionaryConverter))]
public class Parent
{
// The converter defined above should serialize this as a JSON object
[JsonProperty("child")] public NotQuiteADictionary Child { get; set; }
}
public class NotQuiteADictionary
{
private readonly SortedDictionary<string, string> _contents = new SortedDictionary<string, string>();
public void Add(string key, string value)
{
_contents[key] = value;
}
public IReadOnlyDictionary<string, string> ToDictionary()
{
return _contents;
}
}
public class NotQuiteADictionaryConverter : JsonConverter<NotQuiteADictionary>
{
public override void WriteJson(JsonWriter writer, NotQuiteADictionary value, JsonSerializer serializer)
{
// Serialize the instances to a dictionary where the keys and values are
// from the dictionary defined in a field (property) inside the class
serializer.Serialize(writer, value.ToDictionary());
}
public override NotQuiteADictionary ReadJson(JsonReader reader, Type objectType,
NotQuiteADictionary existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class JsonSerializationTest
{
private readonly ITestOutputHelper _testOutputHelper;
public JsonSerializationTest(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}
[Fact]
public void CanSerializeNotQuiteADictionaryAsJsonObject()
{
var child = new NotQuiteADictionary();
child.Add("foo", "fooValue");
child.Add("bar", "barValue");
var parent = new Parent()
{
Child = child
};
// Expected JSON, note that the path to the dictionary members is directly on the child, not .child.contents
// {
// "child": {
// "bar": "barValue",
// "foo": "fooValue"
// }
// }
var json = JsonConvert.SerializeObject(parent, Formatting.Indented);
_testOutputHelper.WriteLine(json);
var deserialized = JObject.Parse(json);
Assert.IsType<JObject>(deserialized["child"]);
Assert.Equal("fooValue", deserialized["child"]["foo"].Value<string>());
Assert.Equal("barValue", deserialized["child"]["bar"].Value<string>());
Assert.Equal(2, deserialized["child"].Count());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment