JSON.对自定义格式进行字符串化
JSON.stringify custom formatting
我正在寻找一种将JSON对象写入文件的方法,但与原始格式保持相同。我已经设法使用writeFileSync(路径,数据)和JSON.stringify()编写内容,但努力弄清楚如何自定义格式。选项JSON。Stringify似乎只对空格的数量进行格式化。
是否有任何方法使用JSON。Stringify生成以下格式
{
"key1" :{"key": "value1","key": "value2"},
"key2" :{"key": "value1","key": "value2"}
}
而不是默认生成的
{
"key1":
{
"key": "value1",
"key": "value2"
},
"key2":
{
"key": "value1",
"key": "value2"
},
}
遗憾的是,您可以使用space参数来定义对象落在树中的间距。你的建议将需要自定义格式化,使用类似正则表达式的东西来格式化字符串后,你的字符串。
下面你会发现一些示例代码来做你想做的事情。您可以将所有这些附加到单个命令中,例如JSON.stringify(myJSON, null, ' ').replace(/: '{'n's+/g, ': {').replace(/",'n's+/g, ', ').replace(/"'n's+'}/g, '}');
,但是为了您可以看到我所做的,我一步一步地将其分解。
const myJSON = {
"key1":{"key": "value1","key2": "value2"},
"key2":{"key": "value1","key2": "value2"}
}
let myString = JSON.stringify(myJSON, null, ' ').replace(/: {/g, `${' '.repeat(5)}: '{`); //Set the key spacing
myString = myString.replace(/: '{'n's+/g, ': {'); //Bring the child bracket on the same line
myString = myString.replace(/",'n's+/g, ', '); //Bring all the other objects for that array up
myString = myString.replace(/"'n's+'}/g, '}'); //Pull the closing bracket on the same line
const myCompactString = JSON.stringify(myJSON, null, ' ').replace(/: {/g, `${' '.repeat(5)}: '{`).replace(/: '{'n's+/g, ': {').replace(/",'n's+/g, ', ').replace(/"'n's+'}/g, '}'); //Done all at once
console.log(`myString: ${myString}`);
console.log(`myCompactString: ${myCompactString}`);
以KevynTD的精彩回答为基础!
防止字符串['song', 'bird']的数组变为{'0':'song', '1': 'bird'}索引键对象。添加if (Array.isArray(this)) obj = this;
到singleLineOBJ函数
const singleLineOBJ = function () {
let obj = { ...this }; // To not change any toJSON
if (Array.isArray(this))
obj = this; // override converting array into object
delete obj.toJSON // To not fall in a stringify loop
我想要这样的格式:
var house = {
family: {
surname: "Smith",
people: 4,
pets: {
dogs: {number:1, names:["toby"]},
cats: {number:2, names:["bob", "boo"]},
platypus: {number:1, names:["perry"], codename: ["agent p"]},
}
},
livingRoom: [
{name:"couch", amount:2},
{name:"shelf", amount:1},
{name:"nightstand", amount:1},
{name:"television", amount:1},
],
bedroom: [
{name:"bed", amount:1},
{name:"wardrobe", amount:1},
{name:"shelf", amount:2},
],
}
这是一个类似的问题,但有更具体的对象键,在一个更复杂的对象树中,它开始变得相当复杂,仅仅用一个正则表达式来做这件事。因此,我使用toJSON和stringify replacer作为工具创建了一个函数来处理这个问题。
我创建的函数有一些限制,比如只能定义单行和多行对象,而不能定义数字或文本列表。它也有一些用于替换方案的特定字符的限制,它们是不寻常的字符,但要确认是否必须替换它们。字符有四个:' π ' (fake '), ' ' ' (fake "), '→'和'←',如果你的对象包含它们中的任何一个,你可以在函数的开头替换它们。
下面是函数工作的例子:
// Custom Stringfy
const customStringify = function (
obj,
replacer,
space = "'t",
{
singlelineObjectKeys = [],
multilineObjectKeys = [],
singlelineChildKeys = [],
multilineChildKeys = [],
singlelineInsideList = [],
}
) {
// WARNING
// - This function will make a mess if your Object contain some of the following characters:
const fakeNewLine = `╗`; // (replace 'n in middle of process)
const fakeTab = `╦`; // (replace 't in middle of process)
const fakeQuote = `║`; // (replace " in middle of process)
const startString = `╠`; // (add to start in middle of process)
const endString = `╣`; // (add to end in middle of process)
// So a solution in this case can be replace this chars by others not used (dont use characters that can mess the regex)
// First make a stringify to solve any toJSON in the main object, then copy the main object stringfied to create all the necessary new toJSON
let objModified = JSON.parse(JSON.stringify(obj, replacer));
// Convert an entire object to single line string
const singleLineOBJ = function () {
// To not change any toJSON
const obj = Array.isArray(this) ? [...this] : { ...this };
// To not fall in a stringify loop
delete obj.toJSON;
// Mark the startString and endString
return (
startString +
JSON.stringify(obj)
// Replace all " by fakeQuote
.replace(/"/g, fakeQuote) +
endString
);
};
// Convert an entire object to multi line string
const multiLineOBJ = function () {
// To not change any toJSON
const obj = Array.isArray(this) ? [...this] : { ...this };
// To not fall in a stringify loop
delete obj.toJSON;
// Mark the startString and endString
return (
startString +
JSON.stringify(obj, null, "'t")
// Replace all " by fakeQuote
.replace(/"/g, fakeQuote)
// Replace 'n using fakeNewLine
.replace(/'n/g, fakeNewLine)
// Replace 't using fakeTab
.replace(/'t/g, fakeTab) +
endString
);
};
// Checks all keys on the object
const throughEveryKey = function (key, value) {
let obj = this;
// objects inside specific keys to become single-line
if (singlelineObjectKeys.includes(key)) {
obj[key].toJSON = singleLineOBJ;
}
// objects inside specific keys to become multi-line
if (multilineObjectKeys.includes(key)) {
obj[key].toJSON = multiLineOBJ;
}
// objects containing the following keys to become single-line
if (singlelineChildKeys.includes(key)) {
obj.toJSON = singleLineOBJ;
}
// objects containing the following keys to become multi-line
if (multilineChildKeys.includes(key)) {
obj.toJSON = multiLineOBJ;
}
// names of list of objects to each list-item become single-line
if (singlelineInsideList.includes(key)) {
obj[key].forEach(
(objectInsideList) => (objectInsideList.toJSON = singleLineOBJ)
);
}
return value;
};
// Just use stringify to go through all object keys, and apply the function to implement "toJSON" in right places, the result of stringify is not used in this case (WIP)
JSON.stringify(objModified, throughEveryKey);
// Use stringfy with right replacers, end result
return (
JSON.stringify(objModified, null, "'t")
// Put in all start of line the right number of Tabs
.replace(new RegExp("(?:(?<=(?<leadTab>^'t*).+?)(?<newLine>" + fakeNewLine + ")(?=.+?))+", "gm"), "$&$1")
// Replace the fake tab by the real one
.replace(new RegExp(fakeTab, "gm"), "'t")
// Replace the fake new line by the real one
.replace(new RegExp(fakeNewLine, "gm"), "'n")
// Replace the fake quote by the real one
.replace(new RegExp(fakeQuote, "gm"), '"')
// Remove start and end of line from the stringfied object
.replace(new RegExp('"' + startString, "gm"), "")
.replace(new RegExp(endString + '"', "gm"), "")
// Replace tab by custom space
.replace(/(?<=^'t*)'t/gm, space)
);
};
var house = {
family: {
surname: "Smith",
people: 4,
pets: {
dogs: {
number: 1,
names: ["toby"],
},
cats: {
number: 2,
names: ["bob", "boo"],
},
platypus: {
number: 1,
names: ["perry"],
codename: ["agent p"],
},
},
},
livingRoom: [
{
name: "couch",
amount: 2,
},
{
name: "shelf",
amount: 1,
},
{
name: "nightstand",
amount: 1,
},
{
name: "television",
amount: 1,
},
],
bedroom: [
{
name: "bed",
amount: 1,
},
{
name: "wardrobe",
amount: 1,
},
{
name: "shelf",
amount: 2,
},
],
};
console.log("A custom stringify:'n'n");
console.log(
customStringify(house, null, " ", {
singlelineObjectKeys: ["dogs", "cats", "platypus"],
multilineObjectKeys: ["family"],
multilineChildKeys: [],
singlelineChildKeys: [],
singlelineInsideList: ["livingRoom", "bedroom"],
})
);
console.log("'n'n'n");
console.log("A normal stringify:'n'n");
console.log(JSON.stringify(house, null, " "));
您需要传递一些信息才能工作,您不需要使用所有内容,但是我会解释我在multiLine和singleLine之间准备格式化的情况:
在上面的例子中,使用的代码是这样的:singlelineObjectKeys:将需要在单行上的对象/数组的键放在这里
multilineObjectKeys:将需要在几行中格式化的对象/数组的键放在这里
multilineChildKeys:如果你不想指定父对象,因为它们可以有很多,为父对象指定一个子键,以便在多行上格式化
singlelineChildKeys:如果你不想指定父对象,因为它们可以有很多,为父对象指定一个子键,以便在单行上格式化
singlelineInsideList:如果您有一个对象列表,并且您希望该列表中的所有对象都在一个列表中格式化,请将该列表的键放在这里
customStringify(house, null, ''t', {
singlelineObjectKeys: ["dogs","cats","platypus"],
multilineObjectKeys: ["family"],
singlelineInsideList: ["livingRoom","bedroom"],
})
但是结果是一样的,例如:
customStringify(house, null, ''t', {
singlelineChildKeys: ["name","names"],
})
由于我在几个地方研究了这个问题,但没有找到任何关于它的信息,我在这里注册了我的解决方案(这是我寻找的地方之一)。请随意使用!
编辑:
- 更新接收列表为单行或多行对象,感谢@mj1701的建议。
- 更新了替换换行符和制表符的方式,使代码速度提高了20%
- 旧的未解决的问题:在定义singlelineInsideList之后,如果你把multilineObjectKeys放在里面,代码选项卡有问题,正在进行
我在空闲时间修改代码,它不是100%完成,但它已经在几个测试用例中工作了。
如果你发现任何错误,请在这里评论!
- 由于布尔值的变化,Django视图中的字符串格式不正确
- JSON字符串格式错误
- Mysql日期时间字符串格式为angularjs中的可读日期
- 挖空 HTML 绑定和字符串格式的 HTML 长度
- 通过javascript将带有日期的字符串格式化为另一种格式
- 将GeoJson字符串格式设置为虚线
- 将JSON转换为特定的字符串格式
- 通过 jQuery 验证日期字符串格式的最佳方法
- 如何以 html 文本的字符串格式放置变量值
- 如何将javascript字符串格式转换为日期
- 使用 javascript 将 ISO 8601 日期字符串格式化为凌晨 0:00
- 如何将 base64 编码的字符串格式化为 x 个字符的可 jslinable 行
- NodeJS 字符串格式,如 Python
- 将字符串格式化为时间格式,如 hh:mm
- 如何获取 g 元素的字符串格式的 svg
- 读取具有“'”的 JSON 字符串(格式不正确?
- 在 JavaScript/Lodash 中将字符串格式化为电话号码
- 如何使用 Angular “数字”过滤器键入时在输入字段中设置带有千和小数分隔符的字符串格式
- JSON 字符串格式
- 是Javascript的一种特殊字符串格式