这是一个示例应用程序,它使用JsonConverter为List显示自定义序列化。我用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();
}
}
}
答案 0 :(得分:1)
在实现JsonConverter时,很容易让读者逻辑错误。很可能你在线上的某个地方读了太多次,这就是以后抛弃序列化器。我建议采用不同的方法,而不是试图找出它离开轨道的位置:在转换器中使用更高级别的LINQ-to-JSON API(JObject),让它与读者打交道。您的代码将更短,更容易理解/维护。
以下是使用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);
}
}