如何使用Javascript从值数组中获取深度嵌套的对象结构

时间:2019-10-06 20:59:35

标签: javascript json prose-mirror

我有JSON表示文本编辑器中的某些内容。这是一个示例:

{ "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" } ] }

这很好,因为我可以安全地将其转换为html,但是它不是在样式中嵌套值,而是在marks子数组中表示此样式。 我希望存储相对于其自然层次结构已经嵌套的数据。

所以代替:

{ 
     "type":"text",
     "marks": [{ "type": "bold" }, { "type": "italic" }],
     "text": "Testing"
}

我想要一些可以更准确地表示结果HTML的东西:

{
  "type" : "bold", 
   "content" : [{ 
       "type" : "italic", 
       "content":[{ 
            "type" : "text", 
            "text" : "Testing"
       }]
   }]
}

我尝试了各种解析json并将其存储的方法,如下所示,但我想我缺少关于javascript如何处理对象的一些基本知识,因为未进行更改。

我已经对json中的每个marks数组进行了以下函数的各种迭代。

item = {type:type, text:text}

marks.forEach((mark)=>{
   let newObj = {content:[], type:mark.type}
    item = newObj.content.push(item)
});

一些额外的背景信息,这是Tipsap所见即所得编辑器基于prosemirror生成的json。我无法使用常规的html导出,因为我正在对数据进行特殊处理。任何帮助将不胜感激。

编辑:达克雷·丹尼(Dacre Denny)使用reduceRight()给出了答案,它回答了问题的第一部分。但是,下面的函数仍然返回原始对象不变。

   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
//

1 个答案:

答案 0 :(得分:2)

一种可能性是使用reduceRight将输入内容的marks子数组“还原”为具有所需“嵌套结构”的单个对象。

这个想法是从{ type : "text", text : content.text }对象(将嵌套)开始缩减,然后用包含“类型”数据的对象增量“包装”该对象。

要为具有元数据类型的对象实现正确的“包装”顺序,需要反向减少marks数组。这就是为什么使用reduceRight(而不是常规的reduce)的原因。

下面是一个示例,用于演示此想法的实际作用:

/* 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"
       }]
   }]
}
*/

希望有帮助!