Etiquetado: OData

Filtros REST $filter con texto no ASCII desde JavaScript

Los servicios OData son muy cómodos pues se pueden consumir desde casi cualquier parte y tecnología. Consumir estos datos desde cualquier aplicación HTML/JavaScript, incluso desde las aplicaciones de Windows 8, es muy sencillo pues nos basta con utilizar las llamadas HTTP de toda la vida para interactuar con el servicio.

Desde las consultas REST podemos filtrar utilizando el parámetro $filter en la url, así podemos consultar el catálogo de películas de Netflix y filtrar para que sólo nos dé las series:
http://odata.netflix.com/v2/Catalog/Titles?$filter=Type eq ‘Series’

En la lengua de Shakespeare no tendremos ningún problema, pero si queremos filtrar con caracteres no ASCII tendremos comportamientos que no serán los que nos esperábamos. Por ejemplo, filtramos por el nombre José dentro del mismo servicio:
http://odata.netflix.com/v2/Catalog/Titles?$filter=substringof(‘José’,Name)
Y obtenemos resultados como este, donde el nombre José no aparece:
netflix_nonasciifilter
De hecho, dependiendo del servicio y desde dónde lo llamemos obtendremos resultados diferentes, pues la interpretación de los caracteres que recibe se puede hacer de varias formas.

La solución está en codificar el filtro dentro de la url, para codificar el texto la función adecuada en JavaScript es encodeURIComponent, pues la función escape produce también resultados no deseados. Podéis probar los ejemplos en jsfiddle, aunque al ser JSONP también produce efectos diferentes según como codifiquemos; podemos comparar el jsfiddle con el resultado de consultar directamente las urls:

En Windows 8 tendremos el mismo problema y lo resolveremos igual, utilizando la función encodeURIComponent:

var query = "José";
var encoded = encodeURIComponent(query);
WinJS.xhr({
    url: "http://odata.netflix.com/v2/Catalog/Titles?$filter=substringof('" +
        encoded + "',Name)&$format=json"
}).then(function (xhr) {
    var result = JSON.parse(xhr.responseText);
    var results = result.d.results;
    // a partir de aquí utilizamos los datos
    var body=document.querySelector("body");
    results.forEach(function (r) {
        var div=document.createElement("div");
        div.textContent=r.Name;
        body.appendChild(div);
    });
});

Antes de acabar, recordad que para enviar la consulta también deberíamos comprobar si el texto a buscar contiene el carácter de comilla simple (‘), pues deberemos sustituirlo por la misma comilla escrita dos veces seguidas (”).
Solucionado con un poco de regex:

query=query.replace(/'/g, "''")

Anuncios