Поделиться через


Пример сериализации слабо типизированных данных JSON

При сериализации пользовательского типа в заданный формат передачи или при десериализации формата передачи в пользовательский тип заданный пользовательский тип должен быть доступен как службе, так и клиенту. Обычно для этого к пользовательским типам применяется атрибут DataContractAttribute , а к их членам применяется атрибут DataMemberAttribute . Этот механизм также применим при работе с объектами JSON, как описано в разделе How to: Serialize and Deserialize JSON Data.

В некоторых сценариях служба Windows Communication Foundation (WCF) или клиент должны получить доступ к объектам JSON, созданным службой или клиентом, находящимся за пределами управления разработчиком. Поскольку дополнительные веб-службы публично предоставляют API JSON, разработчик WCF может создавать локальные определяемые пользователем типы, в которых десериализация произвольных объектов JSON может стать непрактичным.

Пример WeaklyTypedJson предоставляет механизм, позволяющий разработчикам WCF работать с десериализированными, произвольными объектами JSON без создания определяемых пользователем типов. Он называется слабо типизированной сериализацией объектов JSON, поскольку тип, в который десериализуется объект JSON, во время компиляции неизвестен.

Например, API общедоступной веб-службы возвращает следующий объект JSON, который содержит определенные сведения о пользователе службы.

{"personal": {"name": "Paul", "age": 23, "height": 1.7, "isSingle": true, "luckyNumbers": [5,17,21]}, "favoriteBands": ["Band ABC", "Band XYZ"]}

Для десериализации этого объекта клиент WCF должен реализовать следующие определяемые пользователем типы.

[DataContract]
public class MemberProfile
 {
     [DataMember]
     public PersonalInfo personal;

     [DataMember]
     public string[] favoriteBands;
 }

 [DataContract]
public class PersonalInfo
 {
     [DataMember]
     public string name;

     [DataMember]
     public int age;

     [DataMember]
     public double height;

     [DataMember]
     public bool isSingle;

     [DataMember]
     public int[] luckyNumbers;
 }

Эта задача может быть громоздкой, особенно если клиент должен обрабатывать более одного типа объектов JSON.

Тип JsonObject в этом образце является слабо типизированным представлением объекта JSON. JsonObjectиспользует естественное сопоставление между объектами JSON и словарями платформа .NET Framework, а также сопоставление между массивами JSON и массивами платформа .NET Framework. В следующем примере кода демонстрируется тип JsonObject .

// Instantiation of JsonObject json omitted

string name = json["root"]["personal"]["name"];
int age = json["root"]["personal"]["age"];
double height = json["root"]["personal"]["height"];
bool isSingle = json["root"]["personal"]["isSingle"];
int[] luckyNumbers = {
                                     json["root"]["personal"]["luckyNumbers"][0],
                                     json["root"]["personal"]["luckyNumbers"][1],
                                     json["root"]["personal"]["luckyNumbers"][2]
                                 };
string[] favoriteBands = {
                                        json["root"]["favoriteBands"][0],
                                        json["root"]["favoriteBands"][1]
                                    };

Обратите внимание что объекты и массивы JSON можно просматривать без необходимости объявлять их тип во время компиляции. Описание требования к объекту верхнего уровня ["root"] см. в разделе Mapping Between JSON and XML.

Примечание.

Класс JsonObject предоставлен исключительно в качестве примера. Он не был тщательно протестирован, и его не следует использовать в рабочей среде. Очевидным недостатком слабо типизированной сериализации JSON является плохая типобезопасность при работе с JsonObject.

Чтобы использовать тип JsonObject , контракт операции клиента должен использовать в качестве возвращаемого типа Message .

[ServiceContract]
    interface IClientSideProfileService
    {
        // There is no need to write a DataContract for the complex type returned by the service.
        // The client will use a JsonObject to browse the JSON in the received message.

        [OperationContract]
        [WebGet(ResponseFormat = WebMessageFormat.Json)]
        Message GetMemberProfile();
    }

Объект JsonObject создается, как показано в следующем коде.

// Code to instantiate IClientSideProfileService channel omitted…

// Make a request to the service and obtain the Json response
XmlDictionaryReader reader = channel.GetMemberProfile().GetReaderAtBodyContents();

// Go through the Json as though it is a dictionary. There is no need to map it to a .NET CLR type.
JsonObject json = new JsonObject(reader);

Конструктор JsonObject принимает объект XmlDictionaryReader, который получается через метод GetReaderAtBodyContents . Модуль чтения содержит XML-представление сообщения JSON, полученного клиентом. Дополнительные сведения см. в разделе "Сопоставление между JSON и XML".

Программа выдает следующие результаты.

Service listening at http://localhost:8000/.
To view the JSON output from the sample, navigate to http://localhost:8000/GetMemberProfile
This is Paul's page. I am 23 years old and I am 1.7 meters tall.
I am single.
My lucky numbers are 5, 17, and 21.
My favorite bands are Band ABC and Band XYZ.

Настройка, сборка и выполнение образца

  1. Убедитесь, что вы выполнили процедуру однократной установки для примеров Windows Communication Foundation.

  2. Создайте решение WeaklyTypedJson.sln, следуя инструкциям из раздела Building the Windows Communication Foundation Samples.

  3. Запустите решение.