Megosztás:


Gyengén gépelt JSON szerializálási minta

Ha felhasználó által definiált típust szerializál egy adott vezetékes formátumra, vagy egy vezetékformátumot újra felhasználó által definiált típussá deszerializál, az adott felhasználó által definiált típusnak elérhetőnek kell lennie a szolgáltatáson és az ügyfélen is. Ennek elvégzéséhez az attribútumot általában ezekre a DataContractAttribute felhasználó által definiált típusokra alkalmazza a rendszer, és az attribútum a DataMemberAttribute tagokra lesz alkalmazva. Ez a mechanizmus a JavaScript Object Notation (JSON) objektumok használatakor is érvényes, a JSON-adatok szerializálása és deszerializálása című témakörben leírtak szerint.

Bizonyos esetekben a Windows Communication Foundation (WCF) szolgáltatásnak vagy -ügyfélnek hozzá kell férnie egy olyan szolgáltatás vagy ügyfél által létrehozott JSON-objektumokhoz, amelyek nem tartoznak a fejlesztő irányítása alá. Mivel több webszolgáltatás nyilvánosan teszi elérhetővé a JSON API-kat, a WCF-fejlesztő számára nem praktikus helyi, felhasználó által definiált típusokat létrehozni, amelyekbe tetszőleges JSON-objektumokat deszerializálhat.

A WeaklyTypedJson minta olyan mechanizmust biztosít, amellyel a WCF-fejlesztők deszerializált, tetszőleges JSON-objektumokkal dolgozhatnak anélkül, hogy felhasználó által definiált típusokat hoznak létre. Ezt A JSON-objektumok gyengén gépelt szerializálásának nevezzük, mivel a fordításkor nem ismert az a típus, amelybe egy JSON-objektum deszerializálódik.

Egy nyilvános webszolgáltatás API-ja például a következő JSON-objektumot adja vissza, amely a szolgáltatás felhasználójára vonatkozó néhány információt ír le.

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

Az objektum deszerializálásához a WCF-ügyfélnek a következő felhasználó által definiált típusokat kell implementálnia.

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

Ez nehézkes lehet, különösen akkor, ha az ügyfélnek egynél több JSON-objektumot kell kezelnie.

A JsonObject minta által biztosított típus gyengén írja be a deszerializált JSON-objektumot. JsonObjectA JSON-objektumok és a .NET-keretrendszer szótárak közötti természetes leképezésre, valamint a JSON-tömbök és .NET-keretrendszer tömbök közötti leképezésre támaszkodik. Az alábbi kód a típust JsonObject mutatja.

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

Vegye figyelembe, hogy a JSON-objektumok és -tömbök között anélkül "tallózhat", hogy fordításkor deklarálnia kellene a típusukat. A legfelső szintű ["root"] objektum követelményének magyarázatát a JSON és az XML közötti megfeleltetés című témakörben talál.

Feljegyzés

Az JsonObject osztály csak példaként van megadva. Nem tesztelték alaposan, és éles környezetben nem használható. A gyengén gépelt JSON-szerializálás nyilvánvaló következménye a típusbiztonság hiánya a munka során JsonObject.

A JsonObject típus használatához az ügyfélműveleti szerződésnek a visszatérési típusaként kell használnia 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();
    }

Ezt JsonObject követően a rendszer az alábbi kódban látható módon példányosít.

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

A JsonObject konstruktor egy XmlDictionaryReader, a GetReaderAtBodyContents metóduson keresztül kapott eredményt vesz fel. Az olvasó xml-reprezentációt tartalmaz az ügyfél által fogadott JSON-üzenetről. További információt a JSON és az XML közötti megfeleltetés című témakörben talál.

A program a következő kimenetet állítja elő:

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.

A minta beállítása, összeállítása és futtatása

  1. Győződjön meg arról, hogy elvégezte a Windows Communication Foundation-minták egyszeri beállítási eljárását.

  2. A megoldás WeaklyTypedJson.sln a Windows Communication Foundation mintáinak elkészítésében leírtak szerint.

  3. Futtassa a megoldást.