我有一个班级,使用Json.net
public class JsonSerializer
{
public string Serialize(object toSerialaze)
{
return JsonConvert.SerializeObject(toSerialaze);
}
public T Deserialize<T>(string toDeserialaze)
{
return JsonConvert.DeserializeObject<T>(toDeserialaze);
}
}
并向它提供这样一个类的对象
public class Isbn
{
private readonly int _groupCode;
private readonly int _publisherCode;
private readonly int _titleCode;
private readonly int _checkCode;
private static readonly Regex Regex = new Regex(@"^\s*\d*\s*-\s*\d*\s*-\s*\d*\s*-\s*\d*\s*$");
public Isbn(int groupCode, int publisherCode, int titleCode, int checkCode)
{
_groupCode = groupCode;
_publisherCode = publisherCode;
_titleCode = titleCode;
_checkCode = checkCode;
}
public Isbn(string isbn)
{
if (isbn == null)
throw new ArgumentNullException("isbn");
if (isbn == "") return;
if (!IsValid(isbn)) return;
var isbnStrings = isbn.Split(new[] {'-', ' '}, StringSplitOptions.RemoveEmptyEntries);
_groupCode = Convert.ToInt32(isbnStrings[0]);
_publisherCode = Convert.ToInt32(isbnStrings[1]);
_titleCode = Convert.ToInt32(isbnStrings[2]);
_checkCode = Convert.ToInt32(isbnStrings[3]);
}
}
我得到一个例外: 其他信息:无法找到用于类型Library.Isbn的构造函数。一个类应该有一个默认的构造函数,一个带参数的构造函数或一个用JsonConstructor属性标记的构造函数。 我知道,我可能会在反序列化时将[JsonConstructor]放在我需要使用的构造函数之前,但我不希望类Isbn知道Json。 我怎么能以另一种方式做同样的事情?我怎样才能让JsonConverter知道,使用哪两个构造函数?
答案 0 :(得分:2)
一种选择是为序列化设置一个不同的类。然后手动或使用AutoMapper映射到原始文件。
作为奖励,您会发现您的业务对象可以自由重构,而不必担心序列化会对此产生什么影响。因为你是对的,所以不应该知道json。
使用静态方法替换公共构造函数
另一个选择是减少构造函数的数量,我尽量不要多于一个,通常没有(我的意思是没有公共构造函数)。
示例:
public Isbn(int groupCode, int publisherCode, int titleCode, int checkCode)
{
_groupCode = groupCode;
_publisherCode = publisherCode;
_titleCode = titleCode;
_checkCode = checkCode;
}
public static Isbn FromString(string isbn)
{
if (isbn == null)
throw new ArgumentNullException("isbn");
if (isbn == "") return;
if (!IsValid(isbn)) return;
var isbnStrings = isbn.Split(new[] {'-', ' '}, StringSplitOptions.RemoveEmptyEntries);
var groupCode = Convert.ToInt32(isbnStrings[0]);
var publisherCode = Convert.ToInt32(isbnStrings[1]);
var titleCode = Convert.ToInt32(isbnStrings[2]);
var checkCode = Convert.ToInt32(isbnStrings[3]);
return new Isbn(groupCode, publisherCode, titleCode, checkCode);
}
答案 1 :(得分:2)
我认为这个答案有点晚,但有人可能想要使用它。
您可以通过创建自定义JsonConverter
来实现public class IsbnConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Isbn);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartObject)
{
var dict = new Dictionary<string, int>();
serializer.Populate(reader, dict);
return new Isbn(dict["groupCode"], dict["publisherCode"], dict["titleCode"], dict["checkCode"]);
}
if (reader.TokenType == JsonToken.String)
{
return new Isbn((string)reader.Value);
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
您唯一需要的是将此转换为JsonConvert.DeserializeObject
var yourobj = JsonConvert.DeserializeObject<T>(json, new IsbnConverter());
现在反序列化可以适用于json的两个
{ .... , isbn:{groupCode:1,publisherCode:2,titleCode:3,checkCode:4}, ...... }
{ .... , isbn:"1-2-3-4", .... }
对于前任;
public class Book
{
public string Title { get; set; }
public Isbn isbn { get; set; }
}
string json1 = @"{Title:""Title 1"", isbn:{groupCode:1,publisherCode:2,titleCode:3,checkCode:4}}";
string json2 = @"{Title:""Title 2"", isbn:""1-2-3-4""}";
var book1 = JsonConvert.DeserializeObject<Book>(json1, new IsbnConverter());
var book2 = JsonConvert.DeserializeObject<Book>(json2, new IsbnConverter());