Exemplo de serialização JSON com tipagem fraca

Ao serializar um tipo definido pelo usuário para um determinado formato de fio ou desserializar um formato de fio de volta para um tipo definido pelo usuário, o tipo definido pelo usuário deve estar disponível no serviço e no cliente. Normalmente, para fazer isso, o DataContractAttribute atributo é aplicado a esses tipos definidos pelo usuário e o DataMemberAttribute atributo é aplicado a seus membros. Esse mecanismo também se aplica ao trabalhar com objetos JSON (JavaScript Object Notation), conforme descrito no tópico Como serializar e desserializar dados JSON.

Em alguns cenários, um serviço ou cliente do Windows Communication Foundation (WCF) deve acessar objetos JSON gerados por um serviço ou cliente que está fora do controle do desenvolvedor. À medida que mais serviços da Web expõem publicamente APIs JSON, pode se tornar impraticável para o desenvolvedor do WCF construir tipos locais definidos pelo usuário nos quais desserializar objetos JSON arbitrários.

O exemplo WeaklyTypedJson fornece um mecanismo que permite que os desenvolvedores do WCF trabalhem com objetos JSON arbitrários e desserializados, sem criar tipos definidos pelo usuário. Isso é conhecido como serialização de tipo fraco de objetos JSON, porque o tipo no qual um objeto JSON desserializa não é conhecido em tempo de compilação.

Por exemplo, uma API de serviço Web público retorna o seguinte objeto JSON, que descreve algumas informações sobre um usuário do serviço.

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

Para desserializar esse objeto, um cliente WCF deve implementar os seguintes tipos definidos pelo usuário.

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

Isso pode ser complicado, especialmente se o cliente tiver que lidar com mais de um tipo de objeto JSON.

O JsonObject tipo fornecido por este exemplo introduz uma representação fracamente tipada do objeto JSON desserializado. JsonObject depende do mapeamento natural entre objetos JSON e dicionários do .NET Framework e do mapeamento entre matrizes JSON e matrizes do .NET Framework. O código a seguir mostra o JsonObject tipo.

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

Observe que você pode "navegar" por objetos JSON e matrizes sem a necessidade de declarar seu tipo em tempo de compilação. Para obter uma explicação do requisito para o objeto de nível ["root"] superior, consulte o tópico Mapeando entre JSON e XML.

Nota

A JsonObject classe é fornecida apenas como exemplo. Ele não foi exaustivamente testado e não deve ser usado em ambientes de produção. Uma implicação óbvia da serialização JSON de tipo fraco é a falta de segurança de tipo ao trabalhar com JsonObjecto .

Para usar o JsonObject tipo, o contrato de operação do cliente deve usar Message como seu tipo de retorno.

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

O JsonObject é então instanciado como mostrado no código a seguir.

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

O JsonObject construtor leva um XmlDictionaryReader, que é obtido através do GetReaderAtBodyContents método. O leitor contém uma representação XML da mensagem JSON recebida pelo cliente. Para obter mais informações, consulte o tópico Mapeamento entre JSON e XML.

O programa produz a seguinte saída:

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.

Para configurar, compilar e executar o exemplo

  1. Certifique-se de ter executado o procedimento de instalação única para os exemplos do Windows Communication Foundation.

  2. Crie a solução WeaklyTypedJson.sln conforme descrito em Criando os exemplos do Windows Communication Foundation.

  3. Execute a solução.