JsonObjectAttribute可用于序列化实现IEnumerable<的类。 T>作为JSON对象而不是JSON数组
可以找到一个完美的例子here。
由于我拥有控件,因此我可以使用自己定义的类。 但是当我尝试编写一个程序来处理第三方库时,我无法在这些类上添加JsonObjectAttribute。
是否有另一种方法可以告诉JsonConvert.SerializeObject执行类似JsonObjectAttribute的操作?
更新:
以下是我从Json.net文档中复制和粘贴的示例。
[JsonObject]
public class Directory : IEnumerable<string>
{
public string Name { get; set; }
public IList<string> Files { get; set; }
public Directory()
{
Files = new List<string>();
}
public IEnumerator<string> GetEnumerator()
{
return Files.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Directory directory = new Directory
{
Name = "My Documents",
Files =
{
"ImportantLegalDocuments.docx",
"WiseFinancalAdvice.xlsx"
}
};
string json = JsonConvert.SerializeObject(directory, Formatting.Indented);
Console.WriteLine(json);
// {
// "Name": "My Documents",
// "Files": [
// "ImportantLegalDocuments.docx",
// "WiseFinancalAdvice.xlsx"
// ]
// }
现在,只要想到[JsonObject]不在该类定义上,那么如何才能获得相同的结果呢?
答案 0 :(得分:1)
您可以创建一个custom contract resolver来维护应该序列化为对象的类型列表:
public class ObjectOverrideContractResolver : DefaultContractResolver
{
readonly HashSet<Type> overrideObjectTypes;
public ObjectOverrideContractResolver(IEnumerable<Type> overrideObjectTypes)
{
if (overrideObjectTypes == null)
throw new ArgumentNullException();
this.overrideObjectTypes = new HashSet<Type>(overrideObjectTypes);
}
protected override JsonContract CreateContract(Type objectType)
{
if (overrideObjectTypes.Contains(objectType))
{
var contract = CreateObjectContract(objectType);
// Mark get-only properties like Count as ignored
foreach (var property in contract.Properties)
{
if (!property.Writable)
property.Ignored = true;
}
return contract;
}
else
{
var contract = base.CreateContract(objectType);
return contract;
}
}
}
然后在JsonSerializerSettings.ContractResolver
中设置:
var resolver = new ObjectOverrideContractResolver(new[] { typeof(Directory) });
var settings = new JsonSerializerSettings { ContractResolver = resolver };
var json = JsonConvert.SerializeObject(directory, Formatting.Indented, settings);
这会产生您需要的输出。如果需要,可以增强它以检查类型或其任何基类型是否在哈希表中(如果需要)。
请注意,为了获得最佳效果,您应该cache and reuse contract resolvers。