Dela via


JSON-serialiseringsexempel med svag typ

När du serialiserar en användardefinierad typ till ett visst trådformat eller deserialiserar ett trådformat tillbaka till en användardefinierad typ, måste den angivna användardefinierade typen vara tillgänglig för både tjänsten och klienten. För att åstadkomma detta DataContractAttribute tillämpas attributet på dessa användardefinierade typer och DataMemberAttribute attributet tillämpas på deras medlemmar. Den här mekanismen gäller även när du arbetar med JSON-objekt (JavaScript Object Notation), enligt beskrivningen i avsnittet How to: Serialize and Deserialize JSON Data (Så här gör du: Serialisera och deserialisera JSON-data).

I vissa fall måste en Windows Communication Foundation-tjänst (WCF) eller -klient komma åt JSON-objekt som genererats av en tjänst eller klient som ligger utanför utvecklarens kontroll. Eftersom fler webbtjänster offentligt exponerar JSON-API:er kan det bli opraktiskt för WCF-utvecklaren att konstruera lokala användardefinierade typer som godtyckliga JSON-objekt kan deserialiseras i.

Exemplet WeaklyTypedJson innehåller en mekanism som gör det möjligt för WCF-utvecklare att arbeta med deserialiserade, godtyckliga JSON-objekt utan att skapa användardefinierade typer. Detta kallas för svag typ av serialisering av JSON-objekt, eftersom den typ som ett JSON-objekt deserialiserar till inte är känd vid kompileringstiden.

Ett offentligt webbtjänst-API returnerar till exempel följande JSON-objekt, som beskriver viss information om en användare av tjänsten.

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

För att deserialisera det här objektet måste en WCF-klient implementera följande användardefinierade typer.

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

Detta kan vara besvärligt, särskilt om klienten måste hantera mer än en typ av JSON-objekt.

Den JsonObject typ som tillhandahålls av det här exemplet introducerar en svagt typad representation av det deserialiserade JSON-objektet. JsonObject förlitar sig på den naturliga mappningen mellan JSON-objekt och .NET Framework-ordlistor och mappningen mellan JSON-matriser och .NET Framework-matriser. Följande kod visar JsonObject typen.

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

Observera att du kan "bläddra i" JSON-objekt och matriser utan att behöva deklarera sin typ vid kompileringstillfället. En förklaring av kravet för objektet på den översta nivån ["root"] finns i avsnittet Mappning mellan JSON och XML.

Kommentar

Klassen JsonObject tillhandahålls endast som ett exempel. Den har inte testats noggrant och bör inte användas i produktionsmiljöer. En uppenbar implikation av svag typ av JSON-serialisering är bristen på typsäkerhet när du arbetar med JsonObject.

Om du vill använda JsonObject typen måste klientåtgärdskontraktet använda Message som returtyp.

[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 Instansieras sedan enligt följande kod.

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

Konstruktorn JsonObject tar en XmlDictionaryReader, som hämtas via GetReaderAtBodyContents -metoden. Läsaren innehåller en XML-representation av JSON-meddelandet som tas emot av klienten. Mer information finns i avsnittet Mappning mellan JSON och XML.

Programmet genererar följande utdata:

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.

Så här konfigurerar du, skapar och kör exemplet

  1. Kontrollera att du har utfört engångsinstallationsproceduren för Windows Communication Foundation-exempel.

  2. Skapa lösningen WeaklyTypedJson.sln enligt beskrivningen i Skapa Windows Communication Foundation-exempel.

  3. Kör lösningen.