[英]Serialization of properties in JSON.NET throws Exception
這是一個示例應用程序,顯示了使用JsonConverter進行列表的自定義序列化。 我向JsonConvert注冊了一個自定義JsonSerializerSettings。 這些設置安裝了我的ListOfGuidConverter。
當您將List序列化和反序列化為序列化的根對象時,這可以很好地工作。 一旦擁有另一個根對象並且List是一個屬性,JSON.Net就會引發異常,表示意外結束。
我該怎么做才能解決此問題?
謝謝Rich
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using PB8.Peep;
namespace JsonTest
{
class Program
{
static void Main(string[] args)
{
try
{
var ListOfGuidsConverter = new ListJsonConverter<Guid>();
var jss = new JsonSerializerSettings();
jss.Converters.Add(new ListofGuidJsonConverter());
string value1 = JsonConvert.SerializeObject(GetSampleList());
Console.WriteLine(value1);
JsonConvert.DefaultSettings = () => jss;
string value2 = JsonConvert.SerializeObject(GetSampleList());
Console.WriteLine();
Console.WriteLine(value2);
var value3 = JsonConvert.DeserializeObject<List<Guid>>(value2);
string value4 = JsonConvert.SerializeObject(value3);
Console.WriteLine();
Console.WriteLine(value4);
var value5 = JsonConvert.SerializeObject(GetSample());
Console.WriteLine();
Console.WriteLine(value5);
var value6 = JsonConvert.DeserializeObject<Sample>(value5);
var value7 = JsonConvert.SerializeObject(value6);
Console.WriteLine();
Console.WriteLine(value7);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
Console.ReadLine();
}
}
public static List<Guid> GetSampleList()
{
return new List<Guid>
{
Guid.NewGuid(),
Guid.NewGuid(),
Guid.NewGuid()
};
}
public static Sample GetSample()
{
Sample s = new Sample();
s.List1.Add(Guid.NewGuid());
s.List1.Add(Guid.NewGuid());
s.List1.Add(Guid.NewGuid());
s.List1.Add(Guid.NewGuid());
s.List1.Add(Guid.NewGuid());
return s;
}
public class Sample
{
public Sample()
{
List1 = GetSampleList();
}
public List<Guid> List1 { get; set; }
}
}
public class ListofGuidJsonConverter : JsonConverter
{
private const string CapacityPropertyName = "c";
private const string ListPropertyName = "l";
private static readonly Type _type = typeof(List<Guid>);
public override bool CanConvert(Type objectType)
{
bool canConvert = objectType == _type;
return canConvert;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
const int DefaultCapacity = 4;
if (reader.TokenType == JsonToken.StartObject)
reader.Read();
if (reader.TokenType == JsonToken.PropertyName)
reader.Read();
int capacity = DefaultCapacity;
if (reader.TokenType == JsonToken.Integer)
{
capacity = Convert.ToInt32(reader.Value);
reader.Read();
}
var listOfT = new List<Guid>(capacity);
if (reader.TokenType == JsonToken.PropertyName)
reader.Read();
if (reader.TokenType == JsonToken.StartArray)
reader.Read();
for (int i = 0; i < capacity; i++)
{
var item = new Guid(Convert.ToString(reader.Value));
listOfT.Add(item);
reader.Read();
}
if (reader.TokenType == JsonToken.EndArray)
reader.Read();
if (reader.TokenType == JsonToken.EndObject)
reader.Read();
return listOfT;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var listOfT = (List<Guid>)value;
writer.WriteStartObject();
writer.WritePropertyName(CapacityPropertyName);
writer.WriteValue(listOfT.Count);
writer.WritePropertyName(ListPropertyName);
writer.WriteStartArray();
foreach (var item in listOfT)
writer.WriteValue(item);
writer.WriteEndArray();
writer.WriteEndObject();
}
}
}
在實現JsonConverter時很容易使閱讀器邏輯出錯。 您很可能在該行的某處讀取了太多次,這在以后會拋棄串行器。 我建議不要采用其他方法,而是嘗試在轉換器內部使用更高級別的LINQ-to-JSON API(JObjects),然后讓它與讀者打交道,而不是試圖弄清它的出路。 您的代碼將更短,更易理解/可維護。
這是使用LINQ-to-JSON的轉換器的替代實現。 它通過了所有測試。
public class ListofGuidJsonConverter : JsonConverter
{
private const string CapacityPropertyName = "c";
private const string ListPropertyName = "l";
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(List<Guid>));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
int capacity = obj[CapacityPropertyName].Value<int>();
List<Guid> list = new List<Guid>(capacity);
foreach (JToken token in obj[ListPropertyName].Children())
{
list.Add(new Guid(token.ToString()));
}
return list;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
List<Guid> list = (List<Guid>)value;
JObject obj = new JObject();
obj.Add(CapacityPropertyName, list.Count);
JArray array = new JArray();
foreach (Guid guid in list)
{
array.Add(guid.ToString());
}
obj.Add(ListPropertyName, array);
obj.WriteTo(writer);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.