Ejemplo de serialización JSON débilmente tipada

Al serializar un tipo definido por el usuario en un formato de conexión determinado o deserializar un formato de conexión en un tipo definido por el usuario, el tipo definido por el usuario determinado debe estar disponible en el servicio y en el cliente. Normalmente, para lograr esto, se aplica el atributo DataContractAttribute a estos tipos definidos por el usuario y el atributo DataMemberAttribute se aplica a sus miembros. Este mecanismo también se aplica al trabajar con los objetos JSON (JavaScript Object Notation), tal y como se describe en el tema How to: Serialize and Deserialize JSON Data.

En algunos escenarios, un servicio o cliente Windows Communication Foundation (WCF) debe acceder a objetos JSON que genera un servicio o cliente fuera del control del desarrollador. A medida que más servicios web exponen de forma pública las API de JSON, para el desarrollador WCF puede resultar poco práctico la construcción de tipos locales definidos por el usuario en los que deserializar objetos JSON arbitrarios.

En el ejemplo de WeaklyTypedJson se proporciona un mecanismo que permite a los desarrolladores WCF que trabajen con objetos JSON arbitrarios y deserializados, sin crear tipos definidos por el usuario. Esto se conoce como serialización débilmente tipada de objetos JSON, porque no se conoce el tipo en el que un objeto JSON se deserializa en el momento de la compilación.

Por ejemplo, una API pública de servicio Web devuelve el siguiente objeto JSON, que describe información sobre un usuario del servicio.

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

Para deserializar este objeto, un cliente WCF debe implementar los siguientes tipos definidos por el usuario.

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

Esto puede ser embarazoso, sobre todo si el cliente tiene que administrar más de un tipo de objeto JSON.

El tipo JsonObject proporcionado por este ejemplo presenta una representación débilmente tipada del objeto JSON deserializado. JsonObject confía en la asignación natural entre los objetos JSON y diccionarios .NET Framework, así como en la asignación entre las matrices JSON y las matrices de .NET Framework. En el código siguiente se muestra el tipo 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]
                                    };

Observe que puede examinar los objetos y matrices JSON sin necesidad de declarar el tipo en el momento de la compilación. Para acceder a una explicación del requisito del objeto ["root"] de nivel superior, consulte el tema Mapping Between JSON and XML.

Nota

La clase JsonObject solo se proporciona como un ejemplo. No se ha probado en profundidad y no debería usarse en entornos de producción. Una implicación obvia de serialización de JSON débilmente tipada es la falta de seguridad de tipos al trabajar con JsonObject.

Para utilizar el tipo JsonObject , el contrato de operación del cliente debe utilizar Message como su tipo de valor devuelto.

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

Se crean instancias de JsonObject a continuación tal y como se muestran en el código siguiente.

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

El constructor JsonObject toma un XmlDictionaryReader, que se obtiene a través del método GetReaderAtBodyContents . El lector contiene una representación XML del mensaje de JSON recibida por el cliente. Para obtener más información, consulte el tema Asignación entre JSON y XML.

El programa produce el siguiente resultado:

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.

Configurar, compilar y ejecutar el ejemplo

  1. Asegúrese de que ha llevado a cabo el Procedimiento de instalación única para los ejemplos de Windows Communication Foundation.

  2. Compile la solución WeaklyTypedJson.sln tal y como se describe en Building the Windows Communication Foundation Samples.

  3. Ejecute la solución.