@chubbyts/chubbyts-decode-encode
Version:
A simple decode/encode solution for json / jsonx / url-encoded / xml / yaml.
69 lines (68 loc) • 2.43 kB
JavaScript
import { XMLParser } from 'fast-xml-parser';
import { throwableToError } from '@chubbyts/chubbyts-throwable-to-error/dist/throwable-to-error';
import { DATATYPE_ARRAY, DATATYPE_BOOLEAN, DATATYPE_NULL, DATATYPE_NUMBER, DATATYPE_OBJECT, DATATYPE_STRING, } from '../jsonx-datatypes.js';
import { DecodeError } from './decoder.js';
const decodeHtmlEntities = (string) => string.replace(/&#\d+;/gm, (code) => String.fromCharCode(code.match(/\d+/)[0]));
const getNodeName = (node) => {
return node[':@']?.['@_name'];
};
const getNodeType = (node) => {
return Object.keys(node)[0];
};
const convertNullNode = () => {
return null;
};
const convertBooleanNode = (node) => {
return node['json:boolean'][0]['#text'];
};
const convertNumberNode = (node) => {
return node['json:number'][0]['#text'];
};
const convertStringNode = (node) => {
return decodeHtmlEntities(node['json:string'][0]['#text']);
};
const convertNode = (node) => {
switch (getNodeType(node)) {
case DATATYPE_OBJECT:
return convertObjectNode(node);
case DATATYPE_ARRAY:
return convertArrayNode(node);
case DATATYPE_STRING:
return convertStringNode(node);
case DATATYPE_NUMBER:
return convertNumberNode(node);
case DATATYPE_BOOLEAN:
return convertBooleanNode(node);
case DATATYPE_NULL:
return convertNullNode();
}
throw new Error(`Unsupported node: ${JSON.stringify(node)}`);
};
const convertArrayNode = (node) => {
return node['json:array'].map(convertNode);
};
const convertNodeWithName = (node) => {
const name = getNodeName(node);
if (undefined === name) {
throw new Error(`Unsupported node: ${JSON.stringify(node)}`);
}
return [name, convertNode(node)];
};
const convertObjectNode = (node) => {
return Object.fromEntries(node['json:object'].map(convertNodeWithName));
};
export const createJsonxTypeDecoder = () => {
return {
decode: (encodedData) => {
try {
const parser = new XMLParser({ preserveOrder: true, ignoreAttributes: false });
return convertNode(parser.parse(encodedData)[1]);
}
catch (e) {
const error = throwableToError(e);
throw new DecodeError(error.message, error.stack);
}
},
contentType: 'application/jsonx+xml',
};
};