[英]Why does deserialization of nested dictionary throws an exception in C# but works in F#?
I serialize a F# record type to Json with Newtonsoft.Json.FSharp. 我使用Newtonsoft.Json.FSharp将F#记录类型序列化为Json。
type Prices = Dictionary<string, decimal>
type PriceList = {Id:string; Name:string; Date:DateTime; CurrencySymbol:string; Status:Status; Prices:Prices}
let private converters : JsonConverter array =
[| BigIntConverter();
GuidConverter();
ListConverter();
OptionConverter();
MapConverter();
TupleArrayConverter();
UnionConverter();
UriConverter();
CultureInfoConverter() |]
let private settings = JsonSerializerSettings (
Converters = converters,
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore)
let serialize obj = JsonConvert.SerializeObject(obj, settings)
The result in JSON is this: JSON的结果是这样的:
{
"Id": "PriceList20140201",
"Name": "PriceList",
"Date": "2014-02-01T00:00:00+01:00",
"CurrencySymbol": "€",
"Status": 0,
"Prices": {
"ItemCodeA": 512.4,
"ItemCodeB": 471.0
}
}
And if I deserialize this it works fine 如果我反序列化它,它工作正常
JsonConvert.DeserializeObject<PriceList>(text)
Result in F# Interactive: 结果F#Interactive:
val y : PriceList =
{Id = "PriceList20140201";
Name = "PriceList";
Date = 01.04.2014 00:00:00;
CurrencySymbol = "€";
Status = Sale;
Prices =
dict
[("ItemCodeA", 512.4M); ("ItemCodeB", 471.0M);...];}
Now I want to deserialize it in C# using Newtonsoft.Json 现在我想使用Newtonsoft.Json在C#中反序列化它
public class PriceList
{
public string Id { get; set; }
public string Name { get; set; }
public DateTime Date { get; set; }
public string CurrencySymbol { get; set; }
public Status Status { get; set; }
public Prices Prices { get; set; }
}
public class Prices : Dictionary<string, decimal>
{
}
...
JsonConvert.DeserializeObject<PriceList>(json)
This results in an JsonSerializationException: 这会导致JsonSerializationException:
Cannot deserialize the current JSON array (eg [1,2,3]) into type 'Halep.Logic.OfferManagement.Contracts.DataClasses.Pricing.Prices' because the type requires a JSON object (eg {"name":"value"}) to deserialize correctly.
无法将当前JSON数组(例如[1,2,3])反序列化为类型'Halep.Logic.OfferManagement.Contracts.DataClasses.Pricing.Prices',因为该类型需要JSON对象(例如{“name”:“value” })正确反序列化。 To fix this error either change the JSON to a JSON object (eg {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (eg ICollection, IList) like List that can be deserialized from a JSON array.
要修复此错误,请将JSON更改为JSON对象(例如{“name”:“value”})或将反序列化类型更改为数组或实现集合接口的类型(例如ICollection,IList),例如List从JSON数组反序列化。 JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
JsonArrayAttribute也可以添加到类型中以强制它从JSON数组反序列化。 Path 'Prices', line 7, position 13.
路径'价格',第7行,第13位。
I read that I need a CustomConverter for nested dictionaries. 我读到我需要一个CustomConverter来嵌套字典。 But as far as I know it should be possible since version 6.0.?
但据我所知,从版本6.0开始应该可行。 without a custom converter.
没有自定义转换器。 I'm currently using 8.0.3.
我目前正在使用8.0.3。 Why does it work in F# but not in C#?
为什么它在F#中有效而在C#中无效? Is the C# object structure wrong?
C#对象结构是错误的吗?
I tried to replace PriceList directly with Dictionary but same result. 我试图直接用Dictionary替换PriceList但结果相同。
Update The last sentence means I tried this: 更新最后一句话意味着我试过这个:
public class PriceList
{
public string Id { get; set; }
public string Name { get; set; }
public DateTime Date { get; set; }
public string CurrencySymbol { get; set; }
public Status Status { get; set; }
public Dictionary<string, decimal> Prices { get; set; }
}
And got nearly the same Exception: 并得到几乎相同的例外:
Cannot deserialize the current JSON array (eg [1,2,3]) into type 'System.Collections.Generic.Dictionary`2[System.String,System.Decimal]' because the type requires a JSON object (eg {"name":"value"}) to deserialize correctly.
无法将当前JSON数组(例如[1,2,3])反序列化为类型'System.Collections.Generic.Dictionary`2 [System.String,System.Decimal]',因为该类型需要一个JSON对象(例如{“name “:”value“})正确反序列化。 To fix this error either change the JSON to a JSON object (eg {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (eg ICollection, IList) like List that can be deserialized from a JSON array.
要修复此错误,请将JSON更改为JSON对象(例如{“name”:“value”})或将反序列化类型更改为数组或实现集合接口的类型(例如ICollection,IList),例如List从JSON数组反序列化。 JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
JsonArrayAttribute也可以添加到类型中以强制它从JSON数组反序列化。 Path 'Prices', line 7, position 13.
路径'价格',第7行,第13位。
Update 2: Solution This code works. 更新2:解决方案此代码有效。 The last comment of @JustinNiessner led to the solution.
@JustinNiessner的最后评论导致了解决方案。 The problem was that the input was in fact this which contains [ ] instead of { }:
问题是输入实际上是包含[]而不是{}的输入:
{
"Id": "PriceList20140201",
"Name": "PriceList",
"Date": "2014-02-01T00:00:00+01:00",
"CurrencySymbol": "€",
"Status": 0,
"Prices": [
"ItemCodeA": 512.4,
"ItemCodeB": 471.0
]
} }
type Prices = Dictionary<string, decimal>
is a type abbreviation in F# rather than creating a new class that inherits from Dictionary<string, decimal>
as the C# code does: type Prices = Dictionary<string, decimal>
是F#中的类型缩写,而不是像C#代码那样创建一个继承自Dictionary<string, decimal>
的新类:
That is why you're seeing deserialization differences between the two. 这就是为什么你会看到两者之间的反序列化差异。
There are two ways that you can fix this in C#. 有两种方法可以在C#中解决这个问题。 The first would be to create a similar type alias with the
using
directive: 第一种方法是
using
指令创建一个类似的类型别名:
using Prices = System.Collections.Generic.Dictionary<string, object>;
The other would be to simply replace the type with Decimal<string, decimal>
in the PriceList
class definition: 另一种方法是简单地用
PriceList
类定义中的Decimal<string, decimal>
替换类型:
public class PriceList
{
public string Id { get; set; }
public string Name { get; set; }
public DateTime Date { get; set; }
public string CurrencySymbol { get; set; }
public Status Status { get; set; }
public Dictionary<string, decimal> Prices { get; set; }
}
And then the C# Desserialization will work the same way as the F#. 然后C#Desserialization将以与F#相同的方式工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.