Если предположить, что ваш TradeDate
является неизменным (как обычно это происходит в f #), то Json.NET может десериализовать такой тип, найдя один конструктор, который параметризуется, а затем вызовет его, сопоставив аргументы конструктора со свойствами JSONимя, по модулю дела.Аргументы, которые не совпадают, получают значение по умолчанию.Если TradeDate
фактически принимает один DateTime
в качестве ввода, вы получите поведение, которое вы видите.
Например, если мы возьмем упрощенную версию, например, такую:
type TradeDate(date : DateTime) =
member this.Year = date.Year
member this.Month = date.Month
member this.DayOfMonth = date.Day
А затем выполните обход в обход с помощью Json.NET следующим образом:
let t1 = new TradeDate(new DateTime(1997, 12, 25))
let json1 = JsonConvert.SerializeObject(t1)
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1)
let json2 = JsonConvert.SerializeObject(t2)
printfn "\nResult after round-trip:\n%s" json2
В результате получается:
{"Year":1,"Month":1,"DayOfMonth":1}
Именно это вы и видите.Демо-скрипка № 1 здесь .
Итак, какие у вас варианты?Во-первых, вы можете изменить TradeDate
, чтобы получить необходимый конструктор, и пометить его как JsonConstructor
.Он может быть закрытым, если применяется атрибут:
type TradeDate [<JsonConstructor>] private(year : int, month : int, dayOfMonth: int) =
member this.Year = year
member this.Month = month
member this.DayOfMonth = dayOfMonth
new(date : DateTime) = new TradeDate(date.Year, date.Month, date.Day)
Демонстрационная скрипка # 2 здесь .
Во-вторых, если вы не можете изменить TradeDate
или добавитьАтрибуты Json.NET можно добавить для него custom JsonConverter
:
[<AllowNullLiteral>] type private TradeDateDTO(year : int, month : int, dayOfMonth : int) =
member this.Year = year
member this.Month = month
member this.DayOfMonth = dayOfMonth
type TradeDateConverter () =
inherit JsonConverter()
override this.CanConvert(t) = (t = typedefof<TradeDate>)
override this.ReadJson(reader, t, existingValue, serializer) =
let dto = serializer.Deserialize<TradeDateDTO>(reader)
match dto with
| null -> raise (new JsonSerializationException("null TradeDate"))
| _ -> new TradeDate(new DateTime(dto.Year, dto.Month, dto.DayOfMonth)) :> Object
override this.CanWrite = false
override this.WriteJson(writer, value, serializer) =
raise (new NotImplementedException());
и десериализовать следующим образом:
let converter = new TradeDateConverter()
let t2 = JsonConvert.DeserializeObject<TradeDate>(json1, converter)
Demo Fiddle #3 здесь .
Примечания:
Ваш вопрос не включает код для TradeDate
, в частности код для преобразования между DateTime
и представление года / месяца / недели месяца / дня недели.Это оказывается немного нетривиальным, поэтому я не включил его в ответ;см. Расчет недели месяца в .NET и Расчет даты по номеру недели , как это можно сделать.
Подробнее о том, как Json.NET выбирает какой конструктор вызывать для типа с несколькими конструкторами, см. Как работает десериализация JSON в C # .