我正在尝试编写一个JsonConverter
以字符串形式转义HTML的代码,除非[AllowHtml]
已应用了该属性;否则,
private class ObjectWithStrings
{
// will be HTML-escaped
public string Name { get; set; }
// won't be escaped
[AllowHtml]
public string Unsafe { get; set; }
}
所以我试图用一个自定义的ReadJson属性编写一个JsonConverter。
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var s = (string)reader.Value;
if (s == null)
{
return null;
}
// here I need to get a PropertyInfo so I can call GetCustomAttribute<AllowHtmlAttribute>();
var encoded = System.Web.Security.AntiXss.AntiXssEncoder.HtmlEncode(s, useNamedEntities: true);
return encoded;
}
我的差距是,我看不到Json.Net是否会让我知道我正在阅读的属性。因此,我不知道如何获取属性的自定义属性。
有没有办法找出我要序列化的属性,或为这种情况推荐的其他模式?
编辑 :我没有写一个明确的问题;我试图编写一个JsonConverter
反序列化 字符串的
-,请参见上面的实现CanConvert()
。我怀疑选择是我问题的开始。除反序列化特定属性外,我可能需要反序列化具有字符串属性的对象,并进行标准反序列化。
在自定义中JsonConverter
,可以通过Path
从中选择属性来找到要反序列化的JSON属性的名称JsonReader
。
string propertyName = reader.Path.Split('.').Last();
但是,这不能解决您的整体问题。假设JSON属性的名称与您的目标类属性匹配,那么您仍然需要一种获取父对象类型的方法,以便从中获取自定义属性。不幸的是,此信息在转换器内部不可用。转换器仅负责它说可以转换的对象类型(在您的情况下为字符串)以及该对象的子属性(在这种情况下,因为字符串是基元,所以不负责)。因此,要使其正常工作,需要编写转换器以在
父级上运行
类,然后需要处理该类的所有字符串属性。由于您的目标似乎是将HTML编码行为应用于所有类中的所有字符串,因此您将需要一个通用转换器来处理所有非原始类型,这可能会变得非常混乱,具体取决于您尝试的内容反序列化。
幸运的是,有更好的方法。除了使用之外JsonConverter
,您还可以IContractResolver
结合使用自定义项和IValueProvider
来解决此问题。A
ContractResolver
更适合于您想广泛应用某种行为的此类问题。
下面是您需要的代码示例。的CustomResolver
类扩展DefaultContractResolver
由Json.Net提供。该CreateProperties()
方法检查JsonProperty
由基础解析器创建的对象,并将内部HtmlEncodingValueProvider
类的实例附加到未[AllowHtml]
应用属性的任何字符串属性。每个值提供者随后都通过SetValue()
方法处理其目标字符串属性的实际编码。
public class CustomResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
// Find all string properties that do not have an [AllowHtml] attribute applied
// and attach an HtmlEncodingValueProvider instance to them
foreach (JsonProperty prop in props.Where(p => p.PropertyType == typeof(string)))
{
PropertyInfo pi = type.GetProperty(prop.UnderlyingName);
if (pi != null && pi.GetCustomAttribute(typeof(AllowHtmlAttribute), true) == null)
{
prop.ValueProvider = new HtmlEncodingValueProvider(pi);
}
}
return props;
}
protected class HtmlEncodingValueProvider : IValueProvider
{
PropertyInfo targetProperty;
public HtmlEncodingValueProvider(PropertyInfo targetProperty)
{
this.targetProperty = targetProperty;
}
// SetValue gets called by Json.Net during deserialization.
// The value parameter has the original value read from the JSON;
// target is the object on which to set the value.
public void SetValue(object target, object value)
{
var encoded = System.Web.Security.AntiXss.AntiXssEncoder.HtmlEncode((string)value, useNamedEntities: true);
targetProperty.SetValue(target, encoded);
}
// GetValue is called by Json.Net during serialization.
// The target parameter has the object from which to read the string;
// the return value is the string that gets written to the JSON
public object GetValue(object target)
{
// if you need special handling for serialization, add it here
return targetProperty.GetValue(target);
}
}
}
要使用解析器,请创建一个新JsonSerializerSettings
实例,然后将其ContractResolver
属性设置为自定义解析器的新实例,并将设置传递给该JsonConvert.DeserializeObject()
方法。
这是一个简短的演示:
class Program
{
static void Main(string[] args)
{
string json = @"
{
""Name"" : ""<b>Foo Bar</b>"",
""Description"" : ""<p>Bada Boom Bada Bing</p>"",
}";
JsonSerializerSettings settings = new JsonSerializerSettings
{
ContractResolver = new CustomResolver()
};
Foo foo = JsonConvert.DeserializeObject<Foo>(json, settings);
Console.WriteLine("Name: " + foo.Name);
Console.WriteLine("Desc: " + foo.Description);
}
}
class Foo
{
public string Name { get; set; }
[AllowHtml]
public string Description { get; set; }
}
class AllowHtmlAttribute : Attribute { }
这是输出。请注意,该Name
属性获取HTML编码,而该Description
属性未获取HTML编码。
Name: <b>Foo Bar</b>
Desc: <p>Bada Boom Bada Bing</p>
小提琴:https :
//dotnetfiddle.net/cAg4NC
问题内容: 我有一个iOS应用程序,需要处理来自Web服务的响应。响应是包含序列化JSON对象的序列化JSON字符串,如下所示: 请注意,此响应是JSON 字符串 ,而不是JSON对象。我需要做的是将字符串反序列化,这样我就可以得到: 然后我可以用来反序列化为。 但是,我该如何第一步?也就是说,如何“解串”字符串,以便拥有序列化的JSON对象? 仅当顶级对象是数组或字典时才有效;它不适用于字符串。
问题内容: 我有以下代码 我想获得输出: 实际发生的情况: 问题答案:
我有以下代码 我想得到输出: 实际发生的事情:
问题内容: 我有一个对象,即时通讯读取和写入,并从和。我不断收到Java期望的错误,但发现了另一个。 在我的课堂上,我已经实现并拥有一个我认为足够的领域。 我是Java序列化的新手。我在这里想念什么? 编辑 如果有关系,我实际上是在尝试读写 这是完整的痕迹: 问题答案: 您正在读取文件吗?在这种情况下,是否立即添加serialVersionUID无关紧要,它不同于文件中存储的那个,并且会创建异常。
我需要编写一个方法,它接受一些对象、给定对象的类中存在的一些字段名和一些字段值。该值是字段的JSON序列化形式。该方法将获取该值并相应地反序列化它,如下所示: (我实际上只需要检索反序列化的值,而不需要重新设置它,但这使它成为一个更好的示例。)只要Jackson默认的反序列化足够,这就行了。现在让我们假设我有一个带有自定义(de)序列化程序的类: 一个可能的解决方案是手动检查注释。但是,我真的不想
我有多个POJO,对于其中的一些,我希望将所有空字符串反序列化为。