下面是一个示例应用程序,它显示了使用JsonConverter对List进行自定义序列化。我注册一个自定义JsonSerializerSettings与JsonConvert。这些设置已经安装了ListOfGuidConverter。
当您将List作为序列化的根对象进行序列化和反序列化时,这非常有效。只要你有一个不同的根对象并且List是一个JSON属性。Net抛出异常,表示意外结束。
我能做些什么来解决这个问题?
谢谢丰富
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);
}
}