Comment embellir partiellement JSON.stringify ()?
Les utilisateurs peuvent télécharger des fichiers JSON à partir de notre application, que je souhaite mettre en valeur pour un débogage plus facile que si tout était sur une seule ligne. Cependant, cela augmente la taille du fichier de près de 40%, même si l'indentation n'est qu'un seul onglet ou espace.
En guise de compromis, je veux exclure toutes les valeurs avec par exemple la clé "large" de la prettification, comme ceci:
{
"small":
{
"a": 1,
"b": 2,
"large": {"a":1,"b":2,"c":3,"d":"the \"large\" object should not be prettified"}
},
"large": {"a":1,"b":2,"c":3,"d":"the \"large\" object should not be prettified"}
}
J'ai essayé de résoudre cela en utilisant le paramètre de remplacement de JSON.stringify:
JSON.stringify(data,(key,value)=>key==="large"?JSON.stringify(data):value,'\t');
Cependant, les valeurs des clés "grandes" finissent par être échappées:
data =
{
"small":
{
"a": 1,
"b": [2,3,4,5],
"large": {"myarray":[1,2,3,4],"b":2,"c":3,"d":"the \"large\" object should not be prettified"}
},
"large": {"a":1,"b":2,"c":3,"d":"the \"large\" object should not be prettified"}
}
const json = JSON.stringify(data,(key,value)=>key==="large"?JSON.stringify(data):value,'\t');
document.getElementById("json").innerText = json;
<html>
<body>
<pre id="json">
</pre>
</body>
</html>
Comment puis-je éviter que cela ne se produise ou embellir partiellement JSON en JavaScript?
Réponses
Chaque fois que vous appelez JSON.stringifyun objet (ou une partie d'un objet) plus d'une fois , vous allez vous retrouver avec des marques de discours échappées. Dans ce cas, une fois que la JSON.stringifyfonction interne a été appliquée à l'intérieur de la fonction de remplacement, il n'y a aucun moyen de dire à la JSON.stringifyfonction externe de ne pas traiter cette instance comme elle le ferait pour toute autre chaîne.
Donc, je pense que si votre objectif est de stringifier «partiellement» un objet, vous devez écrire une fonction qui implémente cela. Pour ce problème, je suggérerais quelque chose comme ceci:
data = {
"small": {
"a": 1,
"b": [2, 3, 4, 5],
"c": [2, {"test":"example"}, [4,4], 5],
"large": {
"myarray": [1, 2, 3, 4],
"b": 2,
"c": 3,
"d": "the \"large\" object should not be prettified"
}
},
"large": {
"a": 1,
"b": 2,
"c": 3,
"d": "the \"large\" object should not be prettified"
}
}
function print(obj, exclude, space) {
let recur = (obj, spacing, inarray) => {
let txt = '';
if (inarray) {
if (Array.isArray(obj)) {
txt += '[';
for(let i=0;i<obj.length;i++) {
txt += recur(obj[i], spacing + space, true);
};
txt = txt.substr(0, Math.max(1,txt.length - 2)) + ']';
} else if (typeof obj === 'object' && obj !== null) {
txt += '{' + recur(obj, spacing + space, false) + '\n' + spacing + '}';
} else if (typeof obj === 'string') {
txt += obj.replaceAll(/\"/g, '\\"') + '"';
} else {
txt += obj;
};
return txt + ', ';
} else {
for (let key of Object.keys(obj)) {
if (exclude.indexOf(key) !== -1) {
txt += '\n' + spacing + '"' + key + '": ' + JSON.stringify(obj[key]);
} else if (Array.isArray(obj[key])) {
txt += '\n' + spacing + '"' + key + '": [';
for(let i=0;i<obj[key].length;i++) {
txt += recur(obj[key][i], spacing + space, true);
};
txt = txt.substr(0, Math.max(1,txt.length - 2)) + ']';
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
txt += '\n' + spacing + '"' + key + '": {' + recur(obj[key], spacing + space, false) + '\n' + spacing + '}';
} else if (typeof obj[key] === 'string') {
txt += '\n' + spacing + '"' + key + '": "' + obj[key].replaceAll(/\"/g, '\\"') + '"';
} else {
txt += '\n' + spacing + '"' + key + '": ' + obj[key];
};
txt += ',';
};
return txt.substr(0, txt.length - 1);
};
};
return (Array.isArray(obj) ? '[' + recur(obj, space, true) + '\n' + ']' : '{' + recur(obj, space, false) + '\n' + '}');
};
document.getElementById("json").innerText = print(data, ['large'], '\t');
<html>
<body>
<pre id="json">
</pre>
</body>
</html>
Ici, une fonction récursive est utilisée, qui parcourt les clés d'un objet et ajoute la paire clé-valeur à une chaîne, en gérant différents types de données. Si le keyest trouvé dans le excludetableau, il est stringifié.
En parcourant les clés et en appliquant conditionnellement JSON.stringifysi nécessaire, vous évitez efficacement le problème ci-dessus.
Je suis sûr qu'il peut y avoir des cas extrêmes à surveiller lors de l'écriture du JSON vous-même au lieu d'utiliser une fonction intégrée, mais vous pouvez adapter quelque chose comme ça à vos besoins spécifiques.
EDIT: réponse mise à jour pour mieux considérer les tableaux dans l'objet.