c# – 在过滤掉某些属性时序列化JSON.NET JObject

c# – 在过滤掉某些属性时序列化JSON.NET JObject,第1张

概述我的代码中有一个大的任意 JSON结构作为JObject引用. 我想序列化这个结构,除非我遇到一个包含一个名为type的属性的JObject,其值为“encrypted”,然后我想在写入对象之前删除相邻的data属性. 换句话说,如果我遇到这个: { type: "encrypted", name: "some-name", data: "<base64-string>"} 它将被序 我的代码中有一个大的任意 JSON结构作为JObject引用.

我想序列化这个结构,除非我遇到一个包含一个名为type的属性的JObject,其值为“encrypted”,然后我想在写入对象之前删除相邻的data属性.

换句话说,如果我遇到这个:

{  type: "encrypted",name: "some-name",data: "<base64-string>"}

它将被序列化为:

{  type: "encrypted",name: "some-name"}

我不能改变结构,在变异之前克隆它会效率太低,所以我尝试使用JsonConverter如下:

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);    }}

但是,CanConvert函数似乎只是使用不是从JToken派生的类型调用,所以我的WriteJson函数永远不会被调用.

还有另一种方法来实现这一目标吗?

编辑:以下是一些可用于测试的代码:

[TestMethod]public voID ItShouldExcludeEncryptedData(){    var input = JObject.Parse(@"    {        a: {            type: 'encrypted',name: 'some-name',data: 'some-data'        }    }");    var expected = JObject.Parse(@"    {        a: {            type: 'encrypted',}    }");    var output = input.ToString(Formatting.Indented,new RemoveEncryptedDataSerializer());    Assert.AreEqual(        expected.ToString(Formatting.Indented),output);}
解决方法 需要构建转换器来处理JToken,它必须递归工作以确保编辑所有加密数据.

我能够使用以下转换器:

public class RemoveEncryptedDataConverter : JsonConverter{    public overrIDe bool CanConvert(Type objectType)    {        return typeof(JToken).IsAssignableFrom(objectType);    }    public overrIDe object ReadJson(JsonReader reader,JsonSerializer serializer)    {        JToken token = (JToken)value;        if (token.Type == JTokenType.Object)        {            bool omitDataProperty = token.Value<string>("type") == "encrypted";            writer.WriteStartObject();            foreach (var prop in token.Children<JProperty>())            {                if (omitDataProperty && prop.name == "data")                    continue;                writer.WritePropertyname(prop.name);                serializer.Serialize(writer,prop.Value);  // recurse            }            writer.WriteEndobject();        }        else if (token.Type == JTokenType.Array)        {            writer.WriteStartArray();            foreach (var item in token.Children())            {                serializer.Serialize(writer,item);  // recurse            }            writer.WriteEndarray();        }        else // JValue        {            token.Writeto(writer);        }    }}

工作演示:https://dotnetfiddle.net/0K61Bz

如果要直接通过流使用JsonWriter,可以将转换器中的逻辑重构为递归扩展方法并使用它.如果您不使用序列化程序,则不需要转换器.

public static class JsonExtensions{    public static voID RedacteDWriteto(this JToken token,JsonWriter writer)    {        if (token.Type == JTokenType.Object)        {            bool omitDataProperty = token.Value<string>("type") == "encrypted";            writer.WriteStartObject();            foreach (var prop in token.Children<JProperty>())            {                if (omitDataProperty && prop.name == "data")                    continue;                writer.WritePropertyname(prop.name);                prop.Value.RedacteDWriteto(writer);  // recurse            }            writer.WriteEndobject();        }        else if (token.Type == JTokenType.Array)        {            writer.WriteStartArray();            foreach (var item in token.Children())            {                item.RedacteDWriteto(writer);  // recurse            }            writer.WriteEndarray();        }        else // JValue        {            token.Writeto(writer);        }    }}

然后你就可以像这样使用它,其中stream是你的输出流,输入是你的JObject:

using (StreamWriter sw = new StreamWriter(stream))  // or StringWriter if you preferusing (JsonWriter writer = new JsonTextWriter(sw)){    writer.Formatting = Formatting.Indented;    input.RedacteDWriteto(writer);}

小提琴:https://dotnetfiddle.net/l949HU

总结

以上是内存溢出为你收集整理的c# – 在过滤掉某些属性时序列化JSON.NET JObject全部内容,希望文章能够帮你解决c# – 在过滤掉某些属性时序列化JSON.NET JObject所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1233342.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存