[英]How to get deeply nested object structure from array of values with Javascript
I have JSON representing some content in a text editor.我有 JSON 代表文本编辑器中的一些内容。 Here's a sample:
这是一个示例:
{ "type": "doc", "content": [ { "type": "paragraph", "content": [ { "type": "text", "marks": [ { "type": "bold" } ], "text": "Testing" }, { "type": "text", "text": " " }, { "type": "text", "marks": [ { "type": "strike" } ], "text": "Testing " }, { "type": "text", "marks": [ { "type": "strike" }, { "type": "underline" } ], "text": "Testing" }, { "type": "text", "marks": [ { "type": "strike" } ], "text": " Testing" } ] }, { "type": "paragraph" }, { "type": "paragraph", "content": [ { "type": "text", "marks": [ { "type": "bold" } ], "text": "Testing " }, { "type": "text", "marks": [ { "type": "bold" }, { "type": "italic" }, { "type": "strike" } ], "text": "Testing" }, { "type": "text", "marks": [ { "type": "bold" } ], "text": " Testing" } ] }, { "type": "paragraph" } ] }
It's good because I can safely turn it into html, however instead of having nested values for styles, it represents this styling in a marks
sub-array.这很好,因为我可以安全地将其转换为 html,但是它没有为 styles 提供嵌套值,而是在
marks
子数组中表示此样式。 What I would prefer if to store the data already nested with respect to it's natural hierarchy.如果存储已经嵌套的数据相对于它的自然层次结构,我更喜欢什么。
So instead of:所以而不是:
{
"type":"text",
"marks": [{ "type": "bold" }, { "type": "italic" }],
"text": "Testing"
}
I'd like to have something that more accurately represents the resulting HTML:我想要更准确地表示生成的 HTML 的东西:
{
"type" : "bold",
"content" : [{
"type" : "italic",
"content":[{
"type" : "text",
"text" : "Testing"
}]
}]
}
I've tried various ways of parsing the json and storing it like below, but I think I'm missing somethign fundamental about how javascript works with objects, because the changes aren't being made.我尝试了各种解析 json 并将其存储如下的方法,但我认为我缺少关于 javascript 如何与对象一起使用的一些基本知识,因为没有进行更改。
I've done various iteration of the function below, over each marks
array in the json.我在 json 中的每个
marks
数组上对下面的 function 进行了各种迭代。
item = {type:type, text:text}
marks.forEach((mark)=>{
let newObj = {content:[], type:mark.type}
item = newObj.content.push(item)
});
Some extra background information, this is the json generated by the tiptap wysiwyg editor, which is based on prosemirror.一些额外的背景信息,这是基于prosemirror的tiptap所见即所得编辑器生成的json。 I can't use the normal html export because I'm doing special stuff to the data.
我不能使用正常的 html 导出,因为我正在对数据进行特殊处理。 Any help would be greatly appreciated.
任何帮助将不胜感激。
EDIT: Dacre Denny came up with an answer using reduceRight()
which answered the first part of the problem.编辑:Dacre Denny 使用
reduceRight()
提出了一个答案,它回答了问题的第一部分。 However, the function below still returns the original object unchanged.但是,下面的 function 仍然返回原始 object 不变。
const content = editorContent.content
function parseContent (arr) {
arr.forEach((item)=>{
// Check if item contains another array of items, and then iterate
over that one too.
if(item.content){
parseContent(item.content)
}
if(item.marks){
//Extract values from item
// THis is the correct function
const processContent = ({ marks, text }) =>
marks.reduceRight((acc, mark) => ({ type: mark.type, content: [acc]
}), {
type: "text",
text: text
});
item = processContent({ text:item.text, marks:item.marks })
}
})
}
parseContent(content)
return content
//
One possiblity would be to use reduceRight
to "reduce" the marks
sub-array of your input content to a single object with the required "nested structure".一种可能性是使用
reduceRight
将输入内容的marks
子数组“减少”为具有所需“嵌套结构”的单个 object。
The idea is to start the reduction with the { type: "text", text: content.text }
object (that will be nested), and then incrementally "wrap" that object with objects that contain the "type" data.这个想法是从
{ type: "text", text: content.text }
object (将被嵌套)开始减少,然后使用包含“type”数据的对象逐步“包装” object。
To achieve the correct order of "wrapping" for objects with the type metadata, the marks
array needs to be reduced in reverse.为了对元数据类型的对象实现正确的“包装”顺序,需要反向减少
marks
数组。 This is why reduceRight
is used (rather than regular reduce
).这就是使用
reduceRight
的原因(而不是常规的reduce
)。
Here's an example snippet to show this idea in action:这是一个示例片段来展示这个想法的实际效果:
/* Helper function processes the content object, returns the required nested structure */ const processContent = ({ marks, text }) => marks.reduceRight((acc, mark) => ({ type: mark.type, content: [acc] }), { type: "text", text: text }); console.log(processContent({ "type": "text", "marks": [{ "type": "bold" }, { "type": "italic" }], "text": "Testing" })) /* Result: { "type": "bold", "content": [{ "type": "italic", "content":[{ "type": "text", "text": "Testing" }] }] } */
Hope that helps!希望有帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.