我想序列化这个结构,除非我遇到一个包含一个名为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所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)