Json 元组的反序列化问题?
Json deserialization issues with Tuples?
我有一个 class 用于包含所有整数的 3 元组的配置。
public class Configuration
{
public List<Tuple<int, int, int>> MyThreeTuple { get; set; }
public Configuration()
{
MyThreeTuple = new List<Tuple<int, int, int>>();
MyThreeTuple.Add(new Tuple<int, int, int>(-100, 20, 501));
MyThreeTuple.Add(new Tuple<int, int, int>(100, 20, 864));
MyThreeTuple.Add(new Tuple<int, int, int>(500, 20, 1286));
}
}
这个class序列化为Json,System.Web.Script.Serialization
就这样
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
String configJson = jsonSerializer.Serialize(config);
File.WriteAllText(configPath, configJson);
然后在应用程序启动时反序列化
String configJson = File.ReadAllText(configPath);
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
object jsonObject = jsonSerializer.Deserialize(configJson, typeof(ApplicationConfiguration));
appConfig = (Configuration)jsonObject;
我的问题是每当我反序列化 Json 时都会抛出异常
System.MissingMethodException in System.Web.Extensions.dll
随留言
No parameterless constructor defined for type of `System.Tuple`3 ....
这就是为元组生成的 Json 的样子
"MyThreeTuple":
[
{"Item1":-100,"Item2":20,"Item3":501},
{"Item1":100,"Item2":20,"Item3":864},
{"Item1":500,"Item2":20,"Item3":1286}
]
知道如何解决这个问题吗?
编辑:
正如其他人所建议的那样,我尝试了 JSon.NET,它似乎可以反序列化 json。虽然我发现了一个奇怪的怪癖。
所以我的 Configuration
class 的构造函数填写了配置的默认值。具体是上面代码中给出的内容。我发现我可以用不同的值序列化配置,但是反序列化时,默认值也会加载到 List<Tuple<>>
.
我假设 Json.Net 通过首先实例化 Configuration
然后设置其值来解决 Tuple
没有无参数构造函数的问题。
它似乎正在实例化 class,然后 List.Add
将它在 json 中找到的 Tuple
添加到列表中。而不是清除列表然后添加它找到的内容。
JSon.Net中是否有解决此问题的选项?
你得到这个错误的原因是因为 JavascriptSerializer 需要一个 public 无参数构造函数,而 Tuple 不是这种情况,因为它是一个 immutable
在此处 http://json.codeplex.com/ 查看 javascriptserializer 和 json.net
之间的完整比较
中的 Microsoft 状态
Json.NET应该使用序列化和反序列化。为支持 AJAX 的应用程序提供序列化和反序列化功能。
这里有一个关于如何轻松使用 JsonConvert
实现此目的的示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace ConsoleApplication25
{
class Program
{
static void Main(string[] args)
{
Configuration configuration = new Configuration();
string configJson = JsonConvert.SerializeObject(configuration);
File.WriteAllText(configPath, configJson);
//Deserialize the content after you read your file in string
var configurationDeserialized = JsonConvert.DeserializeObject<Configuration>(configJson);
}
}
}
public class Configuration
{
[JsonIgnore]
public List<Tuple<int, int, int>> MyThreeTuple { get; set; }
public Configuration()
{
MyThreeTuple = new List<Tuple<int, int, int>>();
MyThreeTuple.Add(new Tuple<int, int, int>(-100, 20, 501));
MyThreeTuple.Add(new Tuple<int, int, int>(100, 20, 864));
MyThreeTuple.Add(new Tuple<int, int, int>(500, 20, 1286));
}
}
您可以使用 Newtonsoft.Json
解决
- 使用 nuget 安装 Newtonsoft.Json (https://www.nuget.org/packages/Newtonsoft.Json/)
序列化:
var myObject = new Configuration();
var objString = JsonConvert.SerializeObject(myObject);
反序列化:
var result = JsonConvert.DeserializeObject(objString, typeof(Configuration));
或者
var result = JsonConvert.DeserializeObject<Configuration>(objString);
为了完整起见,我想指出 可以使用 JavaScriptSerializer
反序列化 Tuple<int, int, int>
,但您需要 JavaScriptConverter
去做。转换器处理从 JSON 中的值实例化 Tuple
,从而避免异常。
class ThreeTupleConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type> { typeof(Tuple<int, int, int>) }; }
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
int item1 = (int)dictionary["Item1"];
int item2 = (int)dictionary["Item2"];
int item3 = (int)dictionary["Item3"];
return new Tuple<int, int, int>(item1, item2, item3);
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用转换器,您必须像这样向序列化器注册它:
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new List<JavaScriptConverter> { new ThreeTupleConverter() });
然后像往常一样反序列化,它应该可以正常工作:
string configJson = @"
{
""MyThreeTuple"":
[
{ ""Item1"": -100, ""Item2"": 20, ""Item3"": 501 },
{ ""Item1"": 100, ""Item2"": 20, ""Item3"": 864 },
{ ""Item1"": 500, ""Item2"": 20, ""Item3"": 1286 }
]
}";
var config = serializer.Deserialize<Configuration>(configJson);
foreach (var tuple in config.MyThreeTuple)
{
Console.WriteLine("(" + tuple.Item1 + ", " + tuple.Item2 + ", " + tuple.Item3 + ")");
}
输出:
(-100, 20, 501)
(100, 20, 864)
(500, 20, 1286)
我有一个 class 用于包含所有整数的 3 元组的配置。
public class Configuration
{
public List<Tuple<int, int, int>> MyThreeTuple { get; set; }
public Configuration()
{
MyThreeTuple = new List<Tuple<int, int, int>>();
MyThreeTuple.Add(new Tuple<int, int, int>(-100, 20, 501));
MyThreeTuple.Add(new Tuple<int, int, int>(100, 20, 864));
MyThreeTuple.Add(new Tuple<int, int, int>(500, 20, 1286));
}
}
这个class序列化为Json,System.Web.Script.Serialization
就这样
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
String configJson = jsonSerializer.Serialize(config);
File.WriteAllText(configPath, configJson);
然后在应用程序启动时反序列化
String configJson = File.ReadAllText(configPath);
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
object jsonObject = jsonSerializer.Deserialize(configJson, typeof(ApplicationConfiguration));
appConfig = (Configuration)jsonObject;
我的问题是每当我反序列化 Json 时都会抛出异常
System.MissingMethodException in System.Web.Extensions.dll
随留言
No parameterless constructor defined for type of `System.Tuple`3 ....
这就是为元组生成的 Json 的样子
"MyThreeTuple":
[
{"Item1":-100,"Item2":20,"Item3":501},
{"Item1":100,"Item2":20,"Item3":864},
{"Item1":500,"Item2":20,"Item3":1286}
]
知道如何解决这个问题吗?
编辑:
正如其他人所建议的那样,我尝试了 JSon.NET,它似乎可以反序列化 json。虽然我发现了一个奇怪的怪癖。
所以我的 Configuration
class 的构造函数填写了配置的默认值。具体是上面代码中给出的内容。我发现我可以用不同的值序列化配置,但是反序列化时,默认值也会加载到 List<Tuple<>>
.
我假设 Json.Net 通过首先实例化 Configuration
然后设置其值来解决 Tuple
没有无参数构造函数的问题。
它似乎正在实例化 class,然后 List.Add
将它在 json 中找到的 Tuple
添加到列表中。而不是清除列表然后添加它找到的内容。
JSon.Net中是否有解决此问题的选项?
你得到这个错误的原因是因为 JavascriptSerializer 需要一个 public 无参数构造函数,而 Tuple 不是这种情况,因为它是一个 immutable
在此处 http://json.codeplex.com/ 查看 javascriptserializer 和 json.net
之间的完整比较 中的 Microsoft 状态Json.NET应该使用序列化和反序列化。为支持 AJAX 的应用程序提供序列化和反序列化功能。
这里有一个关于如何轻松使用 JsonConvert
实现此目的的示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace ConsoleApplication25
{
class Program
{
static void Main(string[] args)
{
Configuration configuration = new Configuration();
string configJson = JsonConvert.SerializeObject(configuration);
File.WriteAllText(configPath, configJson);
//Deserialize the content after you read your file in string
var configurationDeserialized = JsonConvert.DeserializeObject<Configuration>(configJson);
}
}
}
public class Configuration
{
[JsonIgnore]
public List<Tuple<int, int, int>> MyThreeTuple { get; set; }
public Configuration()
{
MyThreeTuple = new List<Tuple<int, int, int>>();
MyThreeTuple.Add(new Tuple<int, int, int>(-100, 20, 501));
MyThreeTuple.Add(new Tuple<int, int, int>(100, 20, 864));
MyThreeTuple.Add(new Tuple<int, int, int>(500, 20, 1286));
}
}
您可以使用 Newtonsoft.Json
解决- 使用 nuget 安装 Newtonsoft.Json (https://www.nuget.org/packages/Newtonsoft.Json/)
序列化:
var myObject = new Configuration();
var objString = JsonConvert.SerializeObject(myObject);
反序列化:
var result = JsonConvert.DeserializeObject(objString, typeof(Configuration));
或者
var result = JsonConvert.DeserializeObject<Configuration>(objString);
为了完整起见,我想指出 可以使用 JavaScriptSerializer
反序列化 Tuple<int, int, int>
,但您需要 JavaScriptConverter
去做。转换器处理从 JSON 中的值实例化 Tuple
,从而避免异常。
class ThreeTupleConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type> { typeof(Tuple<int, int, int>) }; }
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
int item1 = (int)dictionary["Item1"];
int item2 = (int)dictionary["Item2"];
int item3 = (int)dictionary["Item3"];
return new Tuple<int, int, int>(item1, item2, item3);
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用转换器,您必须像这样向序列化器注册它:
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new List<JavaScriptConverter> { new ThreeTupleConverter() });
然后像往常一样反序列化,它应该可以正常工作:
string configJson = @"
{
""MyThreeTuple"":
[
{ ""Item1"": -100, ""Item2"": 20, ""Item3"": 501 },
{ ""Item1"": 100, ""Item2"": 20, ""Item3"": 864 },
{ ""Item1"": 500, ""Item2"": 20, ""Item3"": 1286 }
]
}";
var config = serializer.Deserialize<Configuration>(configJson);
foreach (var tuple in config.MyThreeTuple)
{
Console.WriteLine("(" + tuple.Item1 + ", " + tuple.Item2 + ", " + tuple.Item3 + ")");
}
输出:
(-100, 20, 501)
(100, 20, 864)
(500, 20, 1286)