I have a large arbitrary JSON structure as a JObject reference in my code.
I want to serialise this structure, except when I encounter a JObject containing a property called type with value "encrypted" then I want to remove the adjacent data property before writing the object.
In other words, if I encounter this:
{
type: "encrypted",
name: "some-name",
data: "<base64-string>"
}
It will be serialized as this:
{
type: "encrypted",
name: "some-name"
}
I can't mutate the structure, and cloning it before mutating would be too inefficient, so I tried using a JsonConverter as follows:
public class RemoveEncryptedDataSerializer : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(JObject);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var o = (JObject)value;
if (o.Value<string>("type") != "encrypted")
{
o.WriteTo(writer);
return;
}
var copy = o.DeepClone();
copy["data"]?.Parent.Remove();
copy.WriteTo(writer);
}
}
However the CanConvert function only seems to be called with types not derived from JToken, so my WriteJson function is never called.
Is there another way to achieve this?
Edit: Here is some code you can use for testing:
[TestMethod]
public void ItShouldExcludeEncryptedData()
{
var input = JObject.Parse(@"
{
a: {
type: 'encrypted',
name: 'some-name',
data: 'some-data'
}
}");
var expected = JObject.Parse(@"
{
a: {
type: 'encrypted',
name: 'some-name',
}
}");
var output = input.ToString(Formatting.Indented, new RemoveEncryptedDataSerializer());
Assert.AreEqual(
expected.ToString(Formatting.Indented),
output);
}
return true;instead ofreturn objectType == typeof(JObject);in yourCanConvertmethod and let me know it it works or not.public override bool CanRead { get { return false; } }WriteJsonis still only called for the leave nodes of the structure.