为什么以及何时需要扁平化JSON对象?

vwhgwdsa  于 2023-11-20  发布在  其他
关注(0)|答案(3)|浏览(181)

我很惊讶StackOverflow上以前没有人问过这个问题。
浏览JSON对象文档和快速google搜索都没有得到满意的结果。
它的优点是什么?它是如何工作的?
编辑:为了更清楚地说明这一点,请看一下这个展平/取消展平的示例。
Fastest way to flatten / un-flatten nested JSON objects
谢谢

alen0pnh

alen0pnh1#

在很多情况下,你会得到一些库自动构建的JSON文本。在整个编程语言中,有许多库构建JSON文本(一个example is here)。
每当库添加一些额外的对象或数组 Package 时,您可能希望摆脱它们,因为您将JSON发送到服务器,并且您的代码在那里崩溃,因为它需要原始值而不是对象(或数组)。或者,如果你的JSON是服务器响应,你不希望得到的JavaScript代码在对象/数组或非对象/数组之间有所不同。在所有这些情况下,扁平化是很有帮助的,因为它可以保存你的时间。2你将不得不实现更少的if/else,你可以可靠地期望你的数据结构尽可能的扁平化。
另一种针对上述场景改进代码的方法是以最健壮的方式编写代码,这样就不会因为多余的 Package 而崩溃。所以总是期待一些 Package 并获取其内容。然后,就不需要扁平化了。
你看,这取决于什么在构建JSON,什么在解析它。构建可能超出了你的范围。
这也导致了数据模型的问题。我曾经处理过XML代码,如果有0个X的条目,或者如果有>0个X的条目,需要以完全不同的方式进行解析。拥有一个允许有0个或更多X条目的 Package 器将使工作更容易。这些都是数据模型决策。
在所有情况下,JSON表示我手动组合的对象结构,我希望它 * 不会改变 *。所以扁平化我设计的细节会令人不安。据我所知,标准操作不需要扁平化(例如JSON.stringify()json_encode()等)。

41zrol4v

41zrol4v2#

这里有一个简单的场景:在Web应用程序中,您有一个正在更新复杂关系对象的HTTP POST。

POST
update=1
&user.id=12345
&[email protected]
&user.profile.name=Mr. Test
&user.profile.age=42
&[email protected]
&[email protected]
&[email protected]
&user.profile.skill.0.id=100
&user.profile.skill.0.name=javascript
&user.profile.skill.1.id=200
&user.profile.skill.1.name=piano

字符串
一切都已经在一个平面结构中了,那么为什么不做一个简单的一对一绑定呢?如果你有一个需要强制执行的约束或安全需求列表,你可以通过直接在排序的键列表上搜索来验证它们。
平面结构更容易让人们理解和使用,甚至与数据库反规范化有一些交叉。它还允许以可读但更详细的方式实现特定于上下文的安全性和约束。
当显示用户的完整视图时,您可能希望隐藏用户技能列表的主键ID的显示。

"user.profile.skill.#.id": { hidden: true, readonly: true }


但是,当直接查看技能时(可能作为管理员编辑它),您可能希望查看ID。

"skill.id": { readonly: true }


如果你正在编写一个以用户为中心/自助服务类型的CMS应用程序,你会得到更多的用户,并且能够使用一个简单的平面模型(底层嵌套关系模型的平面抽象)来贡献,而不是仅仅使用嵌套模型。

**TLDR:平面比嵌套更容易阅读。虽然程序员可以处理嵌套模式,递归解析和处理;但最终用户和管理员通常更喜欢抽象的部分。

5fjcxozz

5fjcxozz3#

我意识到这是一个5年前的问题,但我想,我会把我的想法加进去,以防有人遇到类似的用例,发现这很有用。
你想要扁平化JSON对象的一个用例是通过正则表达式(RegEx)字符串插值进行动态模板绑定。这不是一个很长的句子吗?它只是简单地翻译为**“模板填充字符串而无需硬编码”**。👀😅
想象一个场景,你有一个这样的电子邮件模板字符串:

Hello {{firstName}},

It is amazing you chose to join our site. We are happy to have you on board. 
To get started, we would really love it if you can confirm your email address
by clicking on the link: {{confirm_url}}.

Welcome aboard

The Team!

字符串
给定内存中的以下JSON对象:

{
   "user" : {
               "prefix"      : "Dr.",
               "firstName"   : "Awah",
               "lastName"    : "Teh",
               "email"       : "[email protected]",
               "address"     : {
                                  "street": "100 Main St",
                                  "city"  : "PleasantVille",
                                  "state" : "NY",
                                  "phone" : "+1-212-555-1212"
                               }
            },
   "meta" : {
               "confirm_url" : "http://superduperubercoolsite.com/confirm/ABC123"
            }
}


像这样做正则表达式替换似乎超级简单(假设我们的电子邮件模板字符串存储在名为template的变量中,json对象存储在名为templateData的变量中:

template = template.replace(new RegExp('{{firstName}}', 'g'), templateData.user.firstName);
template = template.replace(new RegExp('{{confirm_url}}', 'g'), templateData.meta.confirm_url);


很简单吧?”实际上是的。这封电子邮件有10个模板字段,或者你想把模板和代码解耦,通过把它存储在一个单独的系统中,比如SendGrid,在那里你冷静的营销头脑可以访问模板并对复制语言进行更改,而不必打电话给工程师来更改代码,测试代码并重新部署到生产环境(多么麻烦)。

这正是JSON扁平化的地方,保存了一天!

现在有很多方法来扁平化JSON,我写了attached a link to a codepen,它有扁平化JSON的逻辑(实际上,我在方法flattenJSONIntoKVPflattenJSONIntoRAW中演示了两种相似但不同的方法,请检查!)。
也就是说,还有其他的实现,值得记住的是,这篇文章的重点是讨论为什么JSON扁平化可能有用,而不是如何
继续!假设你把上面的JSON扁平化(使用我的实现,得到键值对),像这样:

[
   { "key": "user.prefix",         "value": "Dr."},
   { "key": "user.firstName",      "value": "Awah"},
   { "key": "user.lastName",       "value": "Teh"},
   { "key": "user.email",          "value": "[email protected]"},
   { "key": "user.address.street", "value": "100 Main St"},
   { "key": "user.address.city",   "value": "{PleasantVille"},
   { "key": "user.address.state",  "value": "NY"},
   { "key": "user.address.phone",  "value": "+1-212-555-1212"},
   { "key": "meta.confirm_url",    "value": "http://superduperubercoolsite.com/confirm/ABC123"},
]

现在,我的朋友,你正在用气体做饭!

为什么,因为现在你可以用JSON对象中的值动态地interpolate模板字符串,而不用太担心JSON的结构(如果它由于应用程序的发展而改变,你不必记住也来这里改变这个插值代码-你只需要更新电子邮件模板本身,注意,它在SendGrid上[根据这个例子])。
那么你说怎么做呢?:简单,迭代。让我们假设从上面展平的存储在一个名为flatJSON的变量中:

///Notice how I use Javascript's native string interpolation to create my RegExp

///Also note that I am replacing the dot (.) in my flattened JSON variable names with a double underscore (__), I only do this because my intended target is SendGrid, and I don't believe it likes dots in its template placeholders.
flatJSON.forEach(kvp=>template = template.replace(new RegExp(`{{${kvp.key.replace(/\./g, '__'}}}`, 'g'), kvp.value));


就是这样,一行代码可以替换10个甚至数百个甚至数千个(好吧,也许不是数千个,但你明白了)。
哦!差点忘了,我们需要更新模板字符串。
请注意,现在在我们的新模板字符串中,我们可以使用一个有点类似于JSON风格的变量来Map回我们最初的JSON(理想情况下,如果SendGrid在其模板占位符中支持点,这看起来会非常好,但唉,不能总是赢得一切!

Hello {{user__firstName}},

It is amazing you chose to join our site. We are happy to have you on board. 
To get started, we would really love it if you can confirm your email address
by clicking on the link: {{meta__confirm_url}}.

Welcome aboard {{user__prefix}} {{user__lastName}}!

The Team!


瞧!
就这样,我们今天在这里取得了一些成果;我们有:
1.解析JSON对象扁平化的原因
1.我们通过codepen example
1.我们甚至概述了一个用例,利用JSON扁平化可以帮助您编写持久的动态代码,随着底层对象结构的变化而发展-并且不需要您利用big bad ugly eval方法(我们可以在另一篇文章中讨论big bad ugly eval)。

相关问题