Может ли Json.NET десериализовать сплющенную строку JSON с точечной записью?

У меня сплющенный JSON:

{
    "CaseName" : "John Doe v. State",
    "CaseDate" : "<some date>",
    "Client.FirstName" : "John",
    "Client.LastName" : "Doe",
    "Client.Email" : "[email protected]"
    etc...
}

Я хочу десериализовать его обратно на эту сущность:

public class Case()
{
    public string CaseName { get; set; }
    public string CaseDate { get; set; }
    public Client Client { get; set; }
}

где Client.FirstName, Client.LastName и Client.Email являются свойствами объекта Client. Используя Json.NET, есть ли способ заставить его разобрать точечную нотацию и десериализировать этот объект правильно? В настоящее время, используя настройки по умолчанию, он сообщает мне, что Client.FirstName не является свойством типа Case.

Ответ 1

Да, вы можете. Вы получите класс из JsonConverter и переопределите CanConvert, чтобы вы могли преобразовать тип Client.

Затем вы переопределите ReadJson и WriteJson для чтения и записи полей литерала JSON.

Для такого буквального JSON, скорее всего, вам понадобится создать JsonConverter для типа Case, так как вам потребуется кэшировать все свойства объекта Client во время сериализации, пока вы не достаточно информации для фактического создания экземпляра Client.

Затем вы вызовете метод Add на JsonConverterCollection экземпляр, открытый Converters свойство на примере JsonSerializer, который вы используете для выполнения сериализации/десериализации.

Обратите внимание, что если вам нужно сделать это для нескольких разных классов, которые могут быть представлены таким образом, вы можете написать одну реализацию JsonConverter и попросить ее найти атрибут свойства. Если свойство имеет атрибут и предоставляет другой объект со свойствами, он будет ожидать чтения/записи точечной нотации.

Следует отметить, что, хотя вы используете точечную нотацию для идентификатора, это очень редко. Если возможно, на стороне, которая создает литерал JSON, он должен делать это следующим образом:

{ 
    CaseName: "John Doe v. State", 
    CaseDate: "<some date>", 
    Client: 
    {
        FirstName: "John", 
        LastName: "Doe", 
        Email: "[email protected]"
    }
} 

Но если предположить, что у вас есть контроль над этой целью. Если вы этого не сделаете, тогда вы не сможете многое сделать.

Если у вас есть контроль, то построение ваших JSON-литералов таким образом будет отрицать необходимость создания пользовательской реализации JsonConverter.

Ответ 2

Хотя только половина проблемы (т.е. не помогает в том, что ваш объект был сплющен)

Вы можете использовать точную нотацию в очень быстро и грязно с помощью простого

MyTargetClass retVal 
= JsonConvert.DeserializeObject<MyTargetClass>(jsonAsString.Replace(".", "_"));

В комбинации с соответствующими именами свойств "_" в MyTargetClass, например.

public class MyTargetClass
{
    public string CaseName {get; set;}
    public DateTime CaseDate {get; set;}
    public string Client_FirstName {get; set;}

    //Other Properties
}