He descargado datos JSON de Instagram que estoy analizando en NodeJS y almacenando en MongoDB. Tengo un problema en el que los caracteres Unicode escapados no muestran los símbolos emoji correctos cuando se muestran en el lado del cliente.
Por ejemplo, aquí hay una propiedad de uno de los archivos JSON que estoy analizando y almacenando:
"title": "@mujenspirits is in the house!NEW York City \u00f0\u009f\u0097\u00bd\u00f0\u009f\u008d\u008e \nImperial Vintner Liquor Store"El ejemplo anterior debería mostrarse así:
¡@mujenspirits está en la casa! NUEVA York 🗽🍎 Imperial Vintner Liquor Store
Pero en cambio se ve así:
¡@mujenspirits está en la casa! NUEVA York City 🗽🎠Imperial Vintner Liquor Store
Encontré otra pregunta SO en la que alguien tenía un problema similar y su solución me funciona en la consola usando una cadena simple, pero cuando se usa con JSON.parse todavía muestra la misma pantalla incorrecta. Esto es lo que estoy usando ahora para analizar los archivos JSON.
export default function parseJsonFile(filepath: string) { const value = fs.readFileSync(filepath) const converted = new Uint8Array( new Uint8Array(Array.prototype.map.call(value, (c) => c.charCodeAt(0))) ) return JSON.parse(new TextDecoder().decode(converted)) }Para la posteridad, encontré una pregunta SO adicional similar a la mía. No había una solución, sin embargo, uno de los comentarios decía:
Los archivos JSON se generaron incorrectamente. Las cadenas representan puntos de código Unicode como códigos de escape, pero son datos UTF-8 decodificados como Latin1
El comentarista sugirió codificar el JSON cargado en latin1 y luego decodificarlo en utf8 , pero esto tampoco funcionó para mí.
import buffer from 'buffer' const value = fs.readFileSync(filepath) const buffered = buffer.transcode(value, 'latin1', 'utf8') return JSON.parse(buffered.toString())No sé casi nada sobre la codificación de caracteres, así que en este momento estoy disparando en la oscuridad buscando una solución.
Una solución fácil es decodificar la cadena con el paquete uft8
npm install utf8Ahora, como ejemplo de uso, mira este código que usa nodejs y expresa:
import express from "express"; import uft8 from "utf8"; const app = express(); app.get("/", (req, res) => { const text = "\u00f0\u009f\u0097\u00bd\u00f0\u009f\u008d\u008e it is a test"; const textDecode = uft8.decode(text); console.log(textDecode); res.send(textDecode); }); const port = process.env.PORT || 5000; app.listen(port, () => { console.log("Server on port 5000"); });El resultado es que en localhost:5000 verás los emojis sin problema. Puedes aplicar esta idea a tu proyecto, para tratar el json con emojis.
Y aquí hay un ejemplo del lado del cliente:
const element= document.getElementById("text") const txt = "\u00f0\u009f\u0097\u00bd\u00f0\u009f\u008d\u008e it is a test" const text= utf8.decode(txt) console.log(text) element.innerHTML= text <script src="https://cdnjs.cloudflare.com/ajax/libs/utf8/2.1.1/utf8.min.js" integrity="sha512-PACCEofNpYYWg8lplUjhaMMq06f4g6Hodz0DlADi+WeZljRxYY7NJAn46O5lBZz/rkDWivph/2WEgJQEVWrJ6Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <p id="text"></p>Puede intentar convertir las secuencias de escape Unicode en bytes antes de analizar el JSON; probablemente, la biblioteca utf8.js pueda ayudarlo con eso.
Alternativamente, la solución que encontró debería funcionar, pero solo después de deserializar el JSON (convertirá cada secuencia de escape Unicode en un carácter). Por lo tanto, debe atravesar el objeto y aplicar la solución a cada cadena
Por ejemplo:
function parseJsonFile(filepath) { const value = fs.readFileSync(filepath); return decodeUTF8(JSON.parse(value)); } function decodeUTF8(data) { if (typeof data === "string") { const utf8 = new Uint8Array( Array.prototype.map.call(data, (c) => c.charCodeAt(0)) ); return new TextDecoder("utf-8").decode(utf8); } if (Array.isArray(data)) { return data.map(decodeUTF8); } if (typeof data === "object") { const obj = {}; Object.entries(data).forEach(([key, value]) => { obj[key] = decodeUTF8(value); }); return obj; } return data; }