簡體   English   中英

為什么嵌套字典的反序列化會在C#中引發異常但在F#中有效?

[英]Why does deserialization of nested dictionary throws an exception in C# but works in F#?

我使用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)

JSON的結果是這樣的:

{
  "Id": "PriceList20140201",
  "Name": "PriceList",
  "Date": "2014-02-01T00:00:00+01:00",
  "CurrencySymbol": "€",
  "Status": 0,
  "Prices": {
    "ItemCodeA": 512.4,
    "ItemCodeB": 471.0
  }
}

如果我反序列化它,它工作正常

JsonConvert.DeserializeObject<PriceList>(text)

結果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);...];}

現在我想使用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)

這會導致JsonSerializationException:

無法將當前JSON數組(例如[1,2,3])反序列化為類型'Halep.Logic.OfferManagement.Contracts.DataClasses.Pricing.Prices',因為該類型需要JSON對象(例如{“name”:“value” })正確反序列化。 要修復此錯誤,請將JSON更改為JSON對象(例如{“name”:“value”})或將反序列化類型更改為數組或實現集合接口的類型(例如ICollection,IList),例如List從JSON數組反序列化。 JsonArrayAttribute也可以添加到類型中以強制它從JSON數組反序列化。 路徑'價格',第7行,第13位。

我讀到我需要一個CustomConverter來嵌套字典。 但據我所知,從版本6.0開始應該可行。 沒有自定義轉換器。 我目前正在使用8.0.3。 為什么它在F#中有效而在C#中無效? C#對象結構是錯誤的嗎?

我試圖直接用Dictionary替換PriceList但結果相同。

更新最后一句話意味着我試過這個:

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; }
}

並得到幾乎相同的例外:

無法將當前JSON數組(例如[1,2,3])反序列化為類型'System.Collections.Generic.Dictionary`2 [System.String,System.Decimal]',因為該類型需要一個JSON對象(例如{“name “:”value“})正確反序列化。 要修復此錯誤,請將JSON更改為JSON對象(例如{“name”:“value”})或將反序列化類型更改為數組或實現集合接口的類型(例如ICollection,IList),例如List從JSON數組反序列化。 JsonArrayAttribute也可以添加到類型中以強制它從JSON數組反序列化。 路徑'價格',第7行,第13位。

更新2:解決方案此代碼有效。 @JustinNiessner的最后評論導致了解決方案。 問題是輸入實際上是包含[]而不是{}的輸入:

{
  "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>是F#中的類型縮寫,而不是像C#代碼那樣創建一個繼承自Dictionary<string, decimal>的新類:

F#類型縮寫

這就是為什么你會看到兩者之間的反序列化差異。

有兩種方法可以在C#中解決這個問題。 第一種方法是using指令創建一個類似的類型別名:

using Prices = System.Collections.Generic.Dictionary<string, object>;

另一種方法是簡單地用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; }
}

然后C#Desserialization將以與F#相同的方式工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM