Cod*_*ops 11 c# serialization class extend json.net
注意:我已在此Feed的底部提供了解决方案.
我有一个C#Win 8应用程序,我正在反序列化一些看起来像这样的json:
{
'Unit': [
{
'name':'House 123',
isAvailable:'no'
},
{
'name':'House 456',
isAvailable:'yes'
}]
}
Run Code Online (Sandbox Code Playgroud)
进入使用此接口的类:
public interface IUnit
{
string Name { get; }
bool isAvailable { get; }
}
Run Code Online (Sandbox Code Playgroud)
但是牛顿软件会抛出一个错误:
解析值时遇到意外的字符:n.Path'Unit [0] .isAvailable,第1行,第42位.
有没有办法根据生成的对象属性类型bool扩展Newtonsoft来解析yes/no或1/0?现在它只适用于真/假.
关于类的自定义转换器有几个帖子,但不是像bool这样的原始类型.
有什么建议?
Cra*_*ntz 17
public class MyBooleanConverter : JsonConverter
{
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var value = reader.Value;
if (value == null || String.IsNullOrWhiteSpace(value.ToString()))
{
return false;
}
if ("yes".Equals(value, StringComparison.OrdinalIgnoreCase))
{
return true;
}
return false;
}
public override bool CanConvert(Type objectType)
{
if (objectType == typeof(String) || objectType == typeof(Boolean))
{
return true;
}
return false;
}
}
public interface IUnit
{
string Name { get; }
[JsonConverter(typeof(MyBooleanConverter))]
bool isAvailable { get; }
}
Run Code Online (Sandbox Code Playgroud)
我会建议这种方法
using System;
using Newtonsoft.Json;
namespace JsonConverters
{
public class BooleanJsonConverter : JsonConverter
{
public override bool CanConvert( Type objectType )
{
return objectType == typeof( bool );
}
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
{
switch ( reader.Value.ToString().ToLower().Trim() )
{
case "true":
case "yes":
case "y":
case "1":
return true;
case "false":
case "no":
case "n":
case "0":
return false;
}
// If we reach here, we're pretty much going to throw an error so let's let Json.NET throw it's pretty-fied error message.
return new JsonSerializer().Deserialize( reader, objectType );
}
public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我想出的。
public class JsonBooleanConverter : JsonConverter
{
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var value = reader.Value.ToString().ToLower().Trim();
switch (value)
{
case "true":
case "yes":
case "y":
case "1":
return true;
}
return false;
}
public override bool CanConvert(Type objectType)
{
if (objectType == typeof(Boolean))
{
return true;
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var myObj = JsonConvert.DeserializeObject<T>(json, new JsonBooleanConverter());
Run Code Online (Sandbox Code Playgroud)
//这就是我想出的...
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace NewtonTest
{
internal class NewtonTest
{
public class Data
{
public IEnumerable<IUnit> Unit { get; set; }
public override string ToString()
{
return string.Format("Data{{Unit=[{0}]}}",
string.Join(", ", Unit.Select(c =>
string.Format("{0} - Single Unit: {1}",
c.Name,
c.isSingleUnit.ToString()))));
}
}
public interface IUnit
{
string Name { get; }
// [JsonConverter(typeof(Converter))]
bool isSingleUnit { get; }
}
public class House : IUnit
{
public House(string name, bool isSingle)
{
this.Name = name;
this.isSingleUnit = isSingle;
}
public string Name { get; private set; }
public bool isSingleUnit { get; private set; }
}
public class Apartment : IUnit
{
public Apartment(string name, bool isSingle)
{
this.Name = name;
this.isSingleUnit = isSingle;
}
public string Name { get; private set; }
public bool isSingleUnit { get; private set; }
}
private static bool ConvertToBool(string value)
{
value =
value.ToUpper().
Replace("YES", "TRUE").
Replace("Y", "TRUE").
Replace("1", "TRUE").
Replace("NO", "FALSE").
Replace("N", "FALSE").
Replace("0", "FALSE");
bool result = false;
bool.TryParse(value, out result);
return result;
}
private class UnitConverter : Newtonsoft.Json.JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof (NewtonTest.IUnit).IsAssignableFrom(objectType);
}
public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue,
Newtonsoft.Json.JsonSerializer serializer)
{
JObject obj = serializer.Deserialize<JToken>(reader) as JObject;
if (obj != null)
{
string result = obj["isSingleUnit"].ToObject<string>();
bool isSingleUnit = ConvertToBool(result);
string name = obj["name"].ToObject<string>();
if (isSingleUnit)
{
return new NewtonTest.House(name, isSingleUnit);
}
else
{
return new NewtonTest.Apartment(name, isSingleUnit);
}
}
else
{
return null;
}
}
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value,
Newtonsoft.Json.JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public static void Main()
{
Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
serializer.Converters.Add(new UnitConverter());
string json =
"{'Unit':[{'name':'Apartment 123',isSingleUnit:'no'},{'name':'House 456',isSingleUnit:'yes'}]}".Replace(
'\'', '\"');
var obj = serializer.Deserialize(new StringReader(json), typeof (Data));
Console.WriteLine(obj);
Console.ReadKey();
}
}
}
Run Code Online (Sandbox Code Playgroud)