展示问题的源代码:https://github.com/Snuffsis/ConverterExample
因此,我有一个问题,它与stackoverflow问题中的问题完全相同:
C# Newtonsoft.Json Custom Deserializer
虽然这个答案对于简单类型的属性(int,bool,string等)是有帮助的,但当需要嵌套对象时,它就不起作用了。因为它抛出了Newtonsoft.Json.JsonSerializationException: Self referecing loop detected for property 'Value' with type ...
的异常,其中类型是json对象,在本例中是soBillingContact。
它应该能够处理这两种JSON格式
示例:
第一个
如果我将对象创建为根,那么关联问题中的解决方案对于对象本身是有效的,只有当它是嵌套对象时,它才成为问题。
我试图避免为每个存在的json对象编写一个自定义的转换器,而是尝试创建一个通用的转换器。这可能是我的问题,也许应该放弃。但只是检查是否有人可能有任何解决方案的想法。
除了上面的解决方案,我还编写了自己的转换器,可以做类似的事情,工作很好。
这是我自己做的代码,当它为一个特定的对象:Main
:
static void Main(string[] args)
{
var vSalesOrder = new SalesOrder()
{
Project = 1,
PrintDescriptionOnInvoice = true,
PrintNoteOnExternalDocuments = true,
SoBillingContact = new Contact
{
Attention = "attention",
Email = "@whatever.se",
Fax = "lolfax"
}
};
var jsonString = JsonConvert.SerializeObject(vSalesOrder);
}
除了一些被遗漏的属性之外,这之后的预期输出应该与上面的json具有类似的结构。SalesOrder
类别:
WrapWithValueConverter代码可以在顶部的链接溢出问题中找到。
public class SalesOrder
{
[JsonProperty("project", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(WrapWithValueConverter<int?>))]
public int? Project { get; set; }
[JsonProperty("printDescriptionOnInvoice", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(WrapWithValueConverter<bool>))]
public bool PrintDescriptionOnInvoice { get; set; }
[JsonProperty("printNoteOnExternalDocuments", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(WrapWithValueConverter<bool>))]
public bool PrintNoteOnExternalDocuments { get; set; }
[JsonProperty("printNoteOnInternalDocuments", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(WrapWithValueConverter<bool>))]
public bool PrintNoteOnInternalDocuments { get; set; }
[JsonProperty("soBillingContact", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(ContactDtoJsonConverter))]
public Contact SoBillingContact { get; set; }
}
ContactDtoJsonConverter
类别:
public class ContactDtoJsonConverter : JsonConverter<Contact>
{
public override bool CanRead => false;
public override bool CanWrite => true;
public override Contact ReadJson(JsonReader reader, Type objectType, Contact existingValue, bool hasExistingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, Contact value, JsonSerializer serializer)
{
var dtoContact = new DtoContact
{
Value = value
};
JToken t = JToken.FromObject(dtoContact);
JObject o = (JObject)t;
o.WriteTo(writer);
}
}
DtoContact
类别:
public class DtoContact
{
[JsonProperty("value", NullValueHandling = NullValueHandling.Ignore)]
public Contact Value { get; set; }
}
Contact
类别:
public class Contact
{
[JsonProperty("overrideContact", NullValueHandling = NullValueHandling.Ignore)]
public bool OverrideContact { get;set; }
[JsonProperty("attention", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringDtoJsonConverter))]
public string Attention { get; set; }
[JsonProperty("email", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringDtoJsonConverter))]
public string Email { get; set; }
[JsonProperty("fax", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringDtoJsonConverter))]
public string Fax { get; set; }
[JsonProperty("name", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringDtoJsonConverter))]
public string Name { get; set; }
[JsonProperty("phone1", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringDtoJsonConverter))]
public string Phone1 { get; set; }
[JsonProperty("phone2", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringDtoJsonConverter))]
public string Phone2 { get; set; }
[JsonProperty("web", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringDtoJsonConverter))]
public string Web { get; set; }
}
StringDtoJsonConverter
类别:
public class StringDtoJsonConverter : JsonConverter<string>
{
public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer)
{
return (string)reader.Value;
}
public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);
if (t.Type != JTokenType.Object)
{
var dtoValue = new DtoString
{
Value = value
};
serializer.Serialize(writer, dtoValue);
}
}
}
2条答案
按热度按时间qltillow1#
您可以尝试以下代码,它不需要任何自定义转换器
ogq8wdun2#
从this answer到 C# Newtonsoft.Json Custom Deserializer 的转换器可以通过将
[JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Serialize)]
应用到DTO.value
来修复,以避免 *Self referecing loop
* 错误,如下所示:请注意,执行此操作将禁用PreserveReferencesHandling。
也就是说,您编写了 It should be able handle these two JSON formats。如果您事先知道需要哪种格式,处理这两种格式的最简单方法是创建一个自定义的契约解析器,在运行时应用转换器。这样做的额外好处是允许您从模型中删除所有
[JsonConverter(typeof(WrapWithValueConverter<T>))]
属性。首先定义以下合同确定程序:
现在,如果您想要 Package 的格式,请使用下列设定进行序列化和还原序列化:
如果您不需要 Package 格式,请进行序列化和反序列化,而不必像往常一样设置解析器。
演示小提琴here。