Przykład serializacji kodu JSON ze słabą kontrolą typów

W przypadku serializacji typu zdefiniowanego przez użytkownika do danego formatu przewodu lub deserializacji formatu przewodu z powrotem do typu zdefiniowanego przez użytkownika dany typ zdefiniowany przez użytkownika musi być dostępny zarówno dla usługi, jak i klienta. Zazwyczaj w tym celu DataContractAttribute atrybut jest stosowany do tych typów zdefiniowanych przez użytkownika, a DataMemberAttribute atrybut jest stosowany do ich elementów członkowskich. Ten mechanizm ma zastosowanie również podczas pracy z obiektami JavaScript Object Notation (JSON), zgodnie z opisem w temacie How to: Serialize i Deserialize danych JSON.

W niektórych scenariuszach usługa lub klient programu Windows Communication Foundation (WCF) musi uzyskiwać dostęp do obiektów JSON generowanych przez usługę lub klienta, który jest poza kontrolą dewelopera. Ponieważ więcej usług sieci Web publicznie uwidacznia interfejsy API JSON, może stać się niepraktyczne dla dewelopera WCF w celu konstruowania lokalnych typów zdefiniowanych przez użytkownika, w których deserializować dowolne obiekty JSON.

Przykład WeaklyTypedJson udostępnia mechanizm, który umożliwia deweloperom WCF pracę z deserializowanymi, dowolnymi obiektami JSON bez tworzenia typów zdefiniowanych przez użytkownika. Jest to nazywane słabo typizowaną serializacji obiektów JSON, ponieważ typ, w którym deserializuje obiekt JSON, nie jest znany w czasie kompilacji.

Na przykład publiczny interfejs API usługi sieci Web zwraca następujący obiekt JSON, który opisuje niektóre informacje o użytkowniku usługi.

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

Aby wykonać deserializowanie tego obiektu, klient WCF musi zaimplementować następujące typy zdefiniowane przez użytkownika.

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

Może to być kłopotliwe, zwłaszcza jeśli klient musi obsłużyć więcej niż jeden typ obiektu JSON.

Typ JsonObject dostarczony przez ten przykład wprowadza słabo typizowaną reprezentację zdeserializowanego obiektu JSON. JsonObject opiera się na naturalnym mapowaniu między obiektami JSON i słownikami programu .NET Framework oraz mapowaniem między tablicami JSON i tablicami .NET Framework. Poniższy kod przedstawia JsonObject typ.

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

Należy pamiętać, że można "przeglądać" obiekty i tablice JSON bez konieczności deklarowania ich typu w czasie kompilacji. Aby uzyskać wyjaśnienie wymagań dotyczących obiektu najwyższego poziomu ["root"] , zobacz temat Mapowanie między formatami JSON i XML.

Uwaga

Klasa JsonObject jest udostępniana tylko jako przykład. Nie został dokładnie przetestowany i nie powinien być używany w środowiskach produkcyjnych. Oczywistym implikacją słabej serializacji JSON jest brak bezpieczeństwa typu podczas pracy z JsonObjectprogramem .

Aby użyć JsonObject typu, kontrakt operacji klienta musi być używany Message jako typ zwracany.

[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();
    }

Element JsonObject jest następnie tworzone, jak pokazano w poniższym kodzie.

// 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);

Konstruktor JsonObject przyjmuje metodę XmlDictionaryReader, która jest uzyskiwana za pomocą GetReaderAtBodyContents metody . Czytnik zawiera reprezentację XML komunikatu JSON odebranego przez klienta. Aby uzyskać więcej informacji, zobacz temat Mapowanie między formatami JSON i XML.

Program generuje następujące dane wyjściowe:

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.

Aby skonfigurować, skompilować i uruchomić przykład

  1. Upewnij się, że wykonano procedurę instalacji jednorazowej dla przykładów programu Windows Communication Foundation.

  2. Skompiluj rozwiązanie WeaklyTypedJson.sln zgodnie z opisem w temacie Building the Windows Communication Foundation Samples (Tworzenie przykładów programu Windows Communication Foundation).

  3. Uruchom rozwiązanie.