【问题标题】:XSLT equivalent for JSONJSON 的 XSLT 等效项
【发布时间】:2010-12-09 17:40:02
【问题描述】:

是否有与 JSON 等效的 XSLT?允许我像 XSLT 对 XML 一样对 JSON 进行转换。

【问题讨论】:

  • 顺便说一句,这将使用哪种语言/平台?
  • @StaxMan XSLT 是一个在许多语言和平台上都有实际实现的标准,我的问题针对的是类似的努力。
  • +1 回答您的问题。许多人似乎忽略或完全不喜欢 XSLT,但这可能只是对它的 XML 冗长的反应。的确,随着 XML 逐渐失宠,使用 XSLT 的机会越来越少,很可惜! JSON 的 XSLT 等价物会很棒。
  • @NicolasLeThierryd'Ennequin 同意。很多人讨厌 XML,因此不屑一顾 XSLT。工具的 XML 生态系统对 Java 开发人员也很重要,这让更多的人望而却步。但在 2000 年代中期,我对 XSLT 很感兴趣,它的强大功能在 XML 生态系统之外没有直接的等价物。我会喜欢 JSON 等价物!
  • 我强烈不同意这个答案的结束。一个简单的改写就足够了:“如何以声明方式将 JSON 重构为 JSON?”

标签: json xslt equivalent language-comparisons


【解决方案1】:

JSON 的 XSLT 等效项 - 候选列表(工具和规范)

工具

1. XSLT

您可以将XSLT for JSON 用于fn:json-to-xml

本节描述了允许使用 XSLT 处理 JSON 数据的工具。

2。 jq

jq 就像用于 JSON 数据的 sed - 您可以使用它来切片、过滤、映射和转换结构化数据,就像 sed、awk、grep 和朋友让您玩文本一样容易。 有针对不同操作系统的安装包。

3。 jj

JJ 是一个命令行实用程序,它提供了一种从 JSON 文档中检索或更新值的快速简单的方法。它在底层由 GJSON 和 SJSON 提供支持。

4. fx

命令行 JSON 处理工具 - 不需要学习新语法 - 纯 JavaScript - 格式化和突出显示 - 独立二进制

5. jl

jl(“JSON lambda”)是一种用于查询和操作 JSON 的小型函数式语言。

6. JOLT

用 Java 编写的 JSON 到 JSON 转换库,其中转换的“规范”本身就是一个 JSON 文档。

7. gron

让 JSON 变得可辨认! gron 将 JSON 转换为离散的分配,以便更容易地 grep 查找您想要的内容并查看它的绝对“路径”。它简化了对返回大量 JSON 但文档很糟糕的 API 的探索。

8. json-e

JSON-e 是一个数据结构参数化系统,用于在 JSON 对象中嵌入上下文。 中心思想是将数据结构视为“模板”,并使用另一个数据结构作为上下文对其进行转换,以生成输出数据结构。

9. JSLT

JSLT 是一个完整的 JSON 查询和转换语言。语言设计的灵感来自 jq、XPath 和 XQuery。

10. JSONata

JSONata 是一种用于 JSON 数据的轻量级查询和转换语言。受 XPath 3.1 的“位置路径”语义的启发,它允许以紧凑和直观的符号表达复杂的查询。

11. JSONPath Plus

分析、转换和选择性地从 JSON 文档(和 JavaScript 对象)中提取数据。 jsonpath-plus 在原始规范的基础上进行了扩展,添加了一些额外的运算符,并明确了一些原始规范没有说明的行为。

12. json-transforms 上次提交时间:2017 年 12 月 1 日

提供一种递归的模式匹配方法来转换 JSON 数据。转换被定义为一组匹配 JSON 对象结构的规则。当匹配发生时,规则会发出转换后的数据,可选择递归转换子对象。

13. json 上次提交时间:2018 年 6 月 23 日

json 是一个用于处理 JSON 的快速 CLI 工具。它是一个单文件 node.js 脚本,没有外部 deps(除了 node.js 本身)。

14. jsawk 上次提交时间:2015 年 3 月 4 日

Jsawk 类似于 awk,但用于 JSON。您使用从标准输入读取的 JSON 对象数组,使用 JavaScript 过滤它们以生成打印到标准输出的结果数组。

15. yate 上次提交时间:2017 年 3 月 13 日

测试可以用作文档https://github.com/pasaran/yate/tree/master/tests

16. jsonpath-object-transform 上次提交时间:2017 年 1 月 18 日

使用 JSONPath 从对象文字中提取数据并基于模板生成新对象。

17. Stapling 上次提交时间:2013 年 9 月 16 日

Stapling 是一个 JavaScript 库,可为 JSON 对象启用 XSLT 格式。 Stapling 不是使用 JavaScript 模板引擎和 text/html 模板,而是让您有机会使用 XSLT 模板(通过 Ajax 异步加载,然后缓存客户端)来解析您的 JSON 数据源。

规格:

JSON 指针定义了一个字符串语法,用于标识一个特定的值 在 JavaScript 对象表示法 (JSON) 文档中。

JSONPath 表达式始终引用 JSON 结构,就像 XPath 表达式与 XML 文档结合使用一样

用于 JSON 的 JSPath 类似于用于 XML 的 XPath。”

JSONiq 背后的主要灵感来源是 XQuery,迄今为止,它已被证明是一种成功且高效的半结构化数据查询语言

【讨论】:

  • 感谢您非常详细和有用的帖子。为了将单行 json 转换为可读形式,jq(您的列表中的 nr.2)对我来说是最佳选择。再次感谢!
  • 我经常使用json_pp 进行漂亮的打印。它适用于许多发行版。
【解决方案2】:

有趣的想法。在 Google 上进行的一些搜索产生了一些感兴趣的页面,包括:

希望这会有所帮助。

【讨论】:

  • 是的,谢谢,这就是我想要的。遗憾的是,该技术并没有更流行,JSON 在 REST 风格的服务中经常被用作返回格式,如果有一种标准的方式来实现对它的转换,那就太好了。
  • 仅链接回答
【解决方案3】:

试试JOLT。它是一个用 Java 编写的 JSON 到 JSON 转换库。

它是专门创建的,因为我们不想玩“JSON -> XML -> XSLT -> XML -> JSON”游戏,并且使用模板进行任何足够复杂的转换都是不可维护的。

【讨论】:

  • +9000:这是一个严肃的项目!胡扎。带有示例的在线演示极大地有助于攀登学习曲线:jolt-demo.appspot.com
【解决方案4】:

XSLT 支持 JSON,如 http://www.w3.org/TR/xslt-30/#json 所示

XML 使用尖括号作为分隔符,JSON 使用大括号、方括号……即。 XML 较少的标记识别比较意味着它针对声明性转换进行了优化,而更多比较(如 switch 语句)出于速度原因假设脚本语言中的命令式代码适用于推测性分支预测。作为直接结果,对于半结构化数据的不同组合,您可能希望将 XSLT 和 javascript 引擎的性能作为响应页面的一部分进行基准测试。对于可忽略的数据负载,转换可能与没有 XML 序列化的 JSON 一样好。 W3 的决定应该基于更好的分析。

【讨论】:

    【解决方案5】:

    jq - lightweight and flexible command-line JSON processor

    它不像 XSLT 那样基于模板,但更简洁。例如将nameaddress 字段提取到数组中:[.name, .address]

    tutorial 介绍了一个转换 Twitter 的 JSON API 的示例(manual 有很多示例)。

    【讨论】:

    • 它更简洁,因为它的功能要少得多。
    • 我没有找到如何递归搜索 Json 树中的给定属性
    • @Daniel 是.. | .attr_name? 你在找什么? (来自stedolan.github.io/jq/manual/#RecursiveDescent:..
    • 可能不如 XSLT 强大,但非常有用且没有 XSLT 复杂
    【解决方案6】:

    我最近发现了一个我喜欢的 JSON 样式工具:https://github.com/twigkit/tempo。非常容易使用的工具——在我看来,它比 XSLT 更容易使用——不需要 XPATH 查询。

    【讨论】:

    • 如果转换的最终结果是 HTML,Tempo 看起来很棒。但是,如果您只想将隐含的结构重新排列为不同的结构,但最终结果是 still JSON。我仍然想要一个 XPath 的模拟,这样我就可以用函数式的方式编写转换。
    • Tempo 确实很有趣,谢谢。但是,您可以将 xml 和 xslt () 发送到浏览器,您的浏览器会将 xslt 应用到 xml,显示您的 xml 的已定义视图,而无需任何进一步的代码。 jsonT / tempo 也应该是这种情况。
    【解决方案7】:

    【讨论】:

      【解决方案8】:

      我最近围绕这个编写了自己的小型库,它试图尽可能接近

      5.1 处理模型 (XSLT REC) https://www.w3.org/TR/xslt#section-Processing-Model

      尽可能(无论如何我都可以),在几行 JavaScript 代码中。

      这里有一些不完全无关紧要的使用示例...

      1。 JSON-to-some-markup:

      小提琴:https://jsfiddle.net/YSharpLanguage/kj9pk8oz/10

      (灵感来自 D.1 文档示例 (XSLT REC) https://www.w3.org/TR/xslt#section-Document-Example

      这里:

      var D1document = {
          type: "document", title: [ "Document Title" ],
          "": [
            { type: "chapter", title: [ "Chapter Title" ],
              "": [
              { type: "section", title: [ "Section Title" ],
                "": [
                  { type: "para", "": [ "This is a test." ] },
                  { type: "note", "": [ "This is a note." ] }
              ] },
              { type: "section", title: [ "Another Section Title" ],
                "": [
                  { type: "para", "": [ "This is ", { emph: "another" }, " test." ] },
                  { type: "note", "": [ "This is another note." ] }
              ] }
            ] }
          ] };
      
      var D1toHTML = { $: [
        [ [ function(node) { return node.type === "document"; } ],
          function(root) {
            return "<html>\r\n\
        <head>\r\n\
          <title>\r\n\
            {title}\r\n".of(root) + "\
          </title>\r\n\
        </head>\r\n\
        <body>\r\n\
      {*}".of(root[""].through(this)) + "\
        </body>\r\n\
      </html>";
          }
        ],
        [ [ function(node) { return node.type === "chapter"; } ],
          function(chapter) {
            return "    <h2>{title}</h2>\r\n".of(chapter) + "{*}".of(chapter[""].through(this));
          }
        ],
        [ [ function(node) { return node.type === "section"; } ],
          function(section) {
            return "    <h3>{title}</h3>\r\n".of(section) + "{*}".of(section[""].through(this));
          }
        ],
        [ [ function(node) { return node.type === "para"; } ],
          function(para) {
            return "    <p>{*}</p>\r\n".of(para[""].through(this));
          }
        ],
        [ [ function(node) { return node.type === "note"; } ],
          function(note) {
            return '    <p class="note"><b>NOTE: </b>{*}</p>\r\n'.of(note[""].through(this));
          }
        ],
        [ [ function(node) { return node.emph; } ],
          function(emph) {
            return "<em>{emph}</em>".of(emph);
          }
        ]
      ] };
      
      console.log(D1document.through(D1toHTML));
      

      ...给出:

      <html>
        <head>
          <title>
            Document Title
          </title>
        </head>
        <body>
          <h2>Chapter Title</h2>
          <h3>Section Title</h3>
          <p>This is a test.</p>
          <p class="note"><b>NOTE: </b>This is a note.</p>
          <h3>Another Section Title</h3>
          <p>This is <em>another</em> test.</p>
          <p class="note"><b>NOTE: </b>This is another note.</p>
        </body>
      </html>
      

      2。 JSON 到 JSON:

      小提琴:https://jsfiddle.net/YSharpLanguage/ppfmmu15/10

      这里:

      // (A "Company" is just an object with a "Team")
      function Company(obj) {
        return obj.team && Team(obj.team);
      }
      
      // (A "Team" is just a non-empty array that contains at least one "Member")
      function Team(obj) {
        return ({ }.toString.call(obj) === "[object Array]") &&
               obj.length &&
               obj.find(function(item) { return Member(item); });
      }
      
      // (A "Member" must have first and last names, and a gender)
      function Member(obj) {
        return obj.first && obj.last && obj.sex;
      }
      
      function Dude(obj) {
        return Member(obj) && (obj.sex === "Male");
      }
      
      function Girl(obj) {
        return Member(obj) && (obj.sex === "Female");
      }
      
      var data = { team: [
        { first: "John", last: "Smith", sex: "Male" },
        { first: "Vaio", last: "Sony" },
        { first: "Anna", last: "Smith", sex: "Female" },
        { first: "Peter", last: "Olsen", sex: "Male" }
      ] };
      
      var TO_SOMETHING_ELSE = { $: [
      
        [ [ Company ],
          function(company) {
            return { some_virtual_dom: {
              the_dudes: { ul: company.team.select(Dude).through(this) },
              the_grrls: { ul: company.team.select(Girl).through(this) }
            } }
          } ],
      
        [ [ Member ],
          function(member) {
            return { li: "{first} {last} ({sex})".of(member) };
          } ]
      
      ] };
      
      console.log(JSON.stringify(data.through(TO_SOMETHING_ELSE), null, 4));
      

      ...给出:

      {
          "some_virtual_dom": {
              "the_dudes": {
                  "ul": [
                      {
                          "li": "John Smith (Male)"
                      },
                      {
                          "li": "Peter Olsen (Male)"
                      }
                  ]
              },
              "the_grrls": {
                  "ul": [
                      {
                          "li": "Anna Smith (Female)"
                      }
                  ]
              }
          }
      }
      

      3。 XSLT 与 JavaScript:

      JavaScript 等价于...

      XSLT 3.0 REC Section 14.4 Example: Grouping Nodes based on Common Values

      (在:http://jsfiddle.net/YSharpLanguage/8bqcd0ey/1

      参照。 https://www.w3.org/TR/xslt-30/#grouping-examples

      在哪里...

      var cities = [
        { name: "Milano",  country: "Italia",      pop: 5 },
        { name: "Paris",   country: "France",      pop: 7 },
        { name: "München", country: "Deutschland", pop: 4 },
        { name: "Lyon",    country: "France",      pop: 2 },
        { name: "Venezia", country: "Italia",      pop: 1 }
      ];
      
      /*
        Cf.
        XSLT 3.0 REC Section 14.4
        Example: Grouping Nodes based on Common Values
      
        https://www.w3.org/TR/xslt-30/#grouping-examples
      */
      var output = "<table>\r\n\
        <tr>\r\n\
          <th>Position</th>\r\n\
          <th>Country</th>\r\n\
          <th>City List</th>\r\n\
          <th>Population</th>\r\n\
        </tr>{*}\r\n\
      </table>".of
        (
          cities.select().groupBy("country")(function(byCountry, index) {
            var country = byCountry[0],
                cities = byCountry[1].select().orderBy("name");
            return "\r\n\
        <tr>\r\n\
          <td>{position}</td>\r\n\
          <td>{country}</td>\r\n\
          <td>{cities}</td>\r\n\
          <td>{population}</td>\r\n\
        </tr>".
              of({ position: index + 1, country: country,
                   cities: cities.map(function(city) { return city.name; }).join(", "),
                   population: cities.reduce(function(sum, city) { return sum += city.pop; }, 0)
                 });
          })
        );
      

      ...给出:

      <table>
        <tr>
          <th>Position</th>
          <th>Country</th>
          <th>City List</th>
          <th>Population</th>
        </tr>
        <tr>
          <td>1</td>
          <td>Italia</td>
          <td>Milano, Venezia</td>
          <td>6</td>
        </tr>
        <tr>
          <td>2</td>
          <td>France</td>
          <td>Lyon, Paris</td>
          <td>9</td>
        </tr>
        <tr>
          <td>3</td>
          <td>Deutschland</td>
          <td>München</td>
          <td>4</td>
        </tr>
      </table>
      

      4。 JSONiq 与 JavaScript:

      JavaScript 等价于...

      JSONiq Use Cases Section 1.1.2. Grouping Queries for JSON

      (在:https://jsfiddle.net/YSharpLanguage/hvo24hmk/3

      参照。 http://jsoniq.org/docs/JSONiq-usecases/html-single/index.html#jsongrouping

      在哪里...

      /*
        1.1.2. Grouping Queries for JSON
        http://jsoniq.org/docs/JSONiq-usecases/html-single/index.html#jsongrouping
      */
      var sales = [
        { "product" : "broiler", "store number" : 1, "quantity" : 20  },
        { "product" : "toaster", "store number" : 2, "quantity" : 100 },
        { "product" : "toaster", "store number" : 2, "quantity" : 50 },
        { "product" : "toaster", "store number" : 3, "quantity" : 50 },
        { "product" : "blender", "store number" : 3, "quantity" : 100 },
        { "product" : "blender", "store number" : 3, "quantity" : 150 },
        { "product" : "socks", "store number" : 1, "quantity" : 500 },
        { "product" : "socks", "store number" : 2, "quantity" : 10 },
        { "product" : "shirt", "store number" : 3, "quantity" : 10 }
      ];
      
      var products = [
        { "name" : "broiler", "category" : "kitchen", "price" : 100, "cost" : 70 },
        { "name" : "toaster", "category" : "kitchen", "price" : 30, "cost" : 10 },
        { "name" : "blender", "category" : "kitchen", "price" : 50, "cost" : 25 },
        {  "name" : "socks", "category" : "clothes", "price" : 5, "cost" : 2 },
        { "name" : "shirt", "category" : "clothes", "price" : 10, "cost" : 3 }
      ];
      
      var stores = [
        { "store number" : 1, "state" : "CA" },
        { "store number" : 2, "state" : "CA" },
        { "store number" : 3, "state" : "MA" },
        { "store number" : 4, "state" : "MA" }
      ];
      
      var nestedGroupingAndAggregate = stores.select().orderBy("state").groupBy("state")
      ( function(byState) {
          var state = byState[0],
              stateStores = byState[1];
          byState = { };
          return (
            (
              byState[state] =
              products.select().orderBy("category").groupBy("category")
              ( function(byCategory) {
                  var category = byCategory[0],
                      categoryProducts = byCategory[1],
                      categorySales = sales.filter(function(sale) {
                        return stateStores.find(function(store) { return sale["store number"] === store["store number"]; }) &&
                               categoryProducts.find(function(product) { return sale.product === product.name; });
                      });
                  byCategory = { };
                  return (
                    (
                      byCategory[category] =
                      categorySales.select().orderBy("product").groupBy("product")
                      ( function(byProduct) {
                          var soldProduct = byProduct[0],
                              soldQuantities = byProduct[1];
                          byProduct = { };
                          return (
                            (
                              byProduct[soldProduct] =
                              soldQuantities.reduce(function(sum, sale) { return sum += sale.quantity; }, 0)
                            ),
                            byProduct
                          );
                      } ) // byProduct()
                    ),
                    byCategory
                  );
              } ) // byCategory()
            ),
            byState
          );
      } ); // byState()
      

      ...给出:

      [
        {
          "CA": [
            {
              "clothes": [
                {
                  "socks": 510
                }
              ]
            },
            {
              "kitchen": [
                {
                  "broiler": 20
                },
                {
                  "toaster": 150
                }
              ]
            }
          ]
        },
        {
          "MA": [
            {
              "clothes": [
                {
                  "shirt": 10
                }
              ]
            },
            {
              "kitchen": [
                {
                  "blender": 250
                },
                {
                  "toaster": 50
                }
              ]
            }
          ]
        }
      ]
      

      克服 JSONPath wrt 的限制也很有用。查询祖先轴,由this SO question(当然还有其他人)提出。

      例如,如何在了解其品牌 ID 的情况下获得杂货商品的折扣,在

      {
       "prods": [
          {
              "info": {
                    "rate": 85
                      },
              "grocery": [
                       {
                        "brand": "C",
                        "brand_id": "984"
                       },
                       {
                        "brand": "D",
                        "brand_id": "254"
                       }
                       ],
               "discount": "15"
          },
          {
              "info": {
                    "rate": 100
                      },
              "grocery": [
                       {
                        "brand": "A",
                        "brand_id": "983"
                       },
                       {
                        "brand": "B",
                        "brand_id": "253"
                       }
                       ],
               "discount": "20"
           }
       ]
      }
      

      ?

      一个可能的解决方案是:

      var products = {
           "prods": [
              {
                  "info": {
                        "rate": 85
                          },
                  "grocery": [
                           {
                            "brand": "C",
                            "brand_id": "984"
                           },
                           {
                            "brand": "D",
                            "brand_id": "254"
                           }
                           ],
                   "discount": "15"
              },
              {
                  "info": {
                        "rate": 100
                          },
                  "grocery": [
                           {
                            "brand": "A",
                            "brand_id": "983"
                           },
                           {
                            "brand": "B",
                            "brand_id": "253"
                           }
                           ],
                   "discount": "20"
               }
           ]
      };
      
      function GroceryItem(obj) {
        return (typeof obj.brand === "string") && (typeof obj.brand_id === "string");
      }
      
          // last parameter set to "true", to grab all the "GroceryItem" instances
          // at any depth:
      var itemsAndDiscounts = [ products ].nodeset(GroceryItem, true).
          map(
            function(node) {
              var item = node.value, // node.value: the current "GroceryItem" (aka "$.prods[*].grocery[*]")
      
                  discount = node.parent. // node.parent: the array of "GroceryItem" (aka "$.prods[*].grocery")
                             parent. // node.parent.parent: the product (aka "$.prods[*]")
                             discount; // node.parent.parent.discount: the product discount
      
              // finally, project into an easy-to-filter form:
              return { id: item.brand_id, discount: discount };
            }
          ),
          discountOfItem983;
      
      discountOfItem983 = itemsAndDiscounts.
        filter
        (
          function(mapped) {
            return mapped.id === "983";
          }
        )
        [0].discount;
      
      console.log("Discount of #983: " + discountOfItem983);
      

      ... 给出:

      Discount of #983: 20
      

      'HTH,

      【讨论】:

        【解决方案9】:

        说缺乏工具表明缺乏需求只是在乞求问题。 Linux 中的 X 或 Y 支持也是如此(为什么要为如此少数的操作系统开发高质量的驱动程序和/或游戏?为什么要关注大型游戏和硬件公司不为其开发的操作系统?)。可能需要使用 XSLT 和 JSON 的人最终会使用一种微不足道的解决方法:将 JSON 转换为 XML。但这不是最佳解决方案,不是吗?

        当您拥有原生 JSON 格式并想在浏览器中“所见即所得”地对其进行编辑时,XSLT 将是解决该问题的充分解决方案。用传统的 javascript 编程来做这件事可能会很痛苦。

        事实上,我已经为 XSLT 实现了一种“石器时代”的方法,使用子字符串解析来解释一些基本的 javascript 命令,例如调用模板、处理子进程等。当然,使用 JSON 对象实现转换引擎是比实现一个成熟的 XML 解析器来解析 XSLT 容易得多。问题是,要使用 XML 模板转换 JSON 对象,您需要解析模板的 XML。

        要使用 XML(或 HTML,或文本或其他)转换 JSON 对象,您需要仔细考虑语法以及需要使用哪些特殊字符来识别转换命令。否则,您最终将不得不为您自己的自定义模板语言设计解析器。走过那条路,我可以告诉你,它并不漂亮。

        更新(2010 年 11 月 12 日):在我的解析器上工作了几周后,我已经能够对其进行优化。预先解析模板并将命令存储为 JSON 对象。转换规则也是 JSON 对象,而模板代码是 HTML 和类似于 shell 代码的自制语法的混合。我已经能够将复杂的 JSON 文档转换为 HTML 来制作文档编辑器。编辑器的代码大约有 1K 行(这是一个私人项目,所以我不能分享它)和 JSON 转换代码的大约 990 行(包括迭代命令、简单比较、模板调用、变量保存和评估)。我计划在 MIT 许可下发布它。如果您想参与,请给我发邮件。

        【讨论】:

          【解决方案10】:

          作为对旧问题的另一个新答案,我建议您查看DefiantJS。它不是 JSON 的 XSLT 等效,它 JSON 的 XSLT。文档的“模板”部分包括以下示例:

          <!-- Defiant template -->
          <script type="defiant/xsl-template">
              <xsl:template name="books_template">
                  <xsl:for-each select="//movie">
                      <xsl:value-of select="title"/><br/>
                  </xsl:for-each>
              </xsl:template>
          </script>
          
          <script type="text/javascript">
          
          var data = {
                  "movie": [
                      {"title": "The Usual Suspects"},
                      {"title": "Pulp Fiction"},
                      {"title": "Independence Day"}
                  ]
              },
              htm = Defiant.render('books_template', data);
          
          console.log(htm);
          // The Usual Suspects<br>
          // Pulp Fiction<br>
          // Independence Day<br>
          

          【讨论】:

            【解决方案11】:

            现在有!我最近创建了一个库,json-transforms,正是为了这个目的:

            https://github.com/ColinEberhardt/json-transforms

            它结合了JSPath、一种以 XPath 为模型的 DSL,以及一种直接受 XSLT 启发的递归模式匹配方法。

            这是一个简单的例子。给定以下 JSON 对象:

            const json = {
              "automobiles": [
                { "maker": "Nissan", "model": "Teana", "year": 2011 },
                { "maker": "Honda", "model": "Jazz", "year": 2010 },
                { "maker": "Honda", "model": "Civic", "year": 2007 },
                { "maker": "Toyota", "model": "Yaris", "year": 2008 },
                { "maker": "Honda", "model": "Accord", "year": 2011 }
              ]
            };
            

            这是一个转换:

            const jsont = require('json-transforms');
            const rules = [
              jsont.pathRule(
                '.automobiles{.maker === "Honda"}', d => ({
                  Honda: d.runner()
                })
              ),
              jsont.pathRule(
                '.{.maker}', d => ({
                  model: d.match.model,
                  year: d.match.year
                })
              ),
              jsont.identity
            ];
            
            const transformed  = jsont.transform(json, rules);
            

            输出如下:

            {
              "Honda": [
                { "model": "Jazz", "year": 2010 },
                { "model": "Civic", "year": 2007 },
                { "model": "Accord", "year": 2011 }
              ]
            }
            

            这个变换由三个规则组成。第一个匹配任何本田制造的汽车,发出一个具有Honda 属性的对象,然后递归匹配。第二条规则匹配任何具有maker 属性的对象,输出modelyear 属性。最后是递归匹配的恒等变换。

            【讨论】:

              【解决方案12】:

              我已经厌倦了那里大量的 JavaScript 模板引擎,以及它们所有的内联 HTML 模板、不同的标记样式等,并决定 build a small library 为 JSON 数据结构启用 XSLT 格式。无论如何都不是火箭科学——它只是将 JSON 解析为 XML,然后用 XSLT 文档格式化。它也很快,不如 Chrome 中的 JavaScript 模板引擎快,但在大多数其他浏览器中,它至少与用于大型数据结构的 JS 引擎替代品一样快。

              【讨论】:

                【解决方案13】:

                我正在使用骆驼路线 umashal(xmljson) -> to(xlst) -> marshal(xmljson)。足够高效(虽然不是 100% 完美),但很简单,如果您已经在使用 Camel。

                【讨论】:

                  【解决方案14】:

                  JSONiq 就是这样一个标准,Zorba 是一个开源 C++ 实现。 JSONiq 也可以看作是添加了 JSON 作为本机数据类型的 XQuery。

                  【讨论】:

                    【解决方案15】:

                    JSLT 非常接近 JSON 等效的 XSLT。它是一种转换语言,您可以在其中以 JSON 语法编写输出的固定部分,然后插入表达式以计算您要在模板中插入的值。

                    一个例子:

                    {
                      "time": round(parse-time(.published, "yyyy-MM-dd'T'HH:mm:ssX") * 1000),
                      "device_manufacturer": .device.manufacturer,
                      "device_model": .device.model,
                      "language": .device.acceptLanguage
                    }
                    

                    它是在 Jackson 之上用 Java 实现的。

                    【讨论】:

                      【解决方案16】:

                      使用 XSLT 转换 JSON 是很有可能的:你需要 JSON2SAX 反序列化器和 SAX2JSON 序列化器。

                      Java 中的示例代码: http://www.gerixsoft.com/blog/json/xslt4json

                      【讨论】:

                        【解决方案17】:

                        Yate (https://github.com/pasaran/yate) 是在 XSLT 之后专门设计的,具有 JPath(JS 的自然 XPath 等效项),可编译为 JavaScript,并且有相当长的生产使用历史。它实际上没有记录,但通读示例和测试就足够了。

                        【讨论】:

                          【解决方案18】:

                          为什么不使用 Mr. Data Coverter 将 JSON 转换为 XML,使用 XSLT 将其转换,然后使用相同的方法将其更改回 JSON。

                          【讨论】:

                          • 如果你想让你的代码以良好的性能为你做这件事,那不是一个选择。
                          【解决方案19】:

                          有关使用纯 JavaScript 以及 XSLT 匹配表达式和递归模板背后的熟悉和声明性模式的工作涂鸦/概念证明,请参阅https://gist.github.com/brettz9/0e661b3093764f496e36

                          (对于 JSON 可能会采用类似的方法。)

                          请注意,该演示还依赖于 JavaScript 1.8 表达式闭包,以便在 Firefox 中表达模板(至少在可能实现方法的 ES6 短格式之前)。

                          免责声明:这是我自己的代码。

                          【讨论】:

                            【解决方案20】:

                            很久以前,我为我的基于杰克逊的 json 处理框架编写了一个 dom 适配器。它使用 nu.xom 库。生成的 dom 树可与 java xpath 和 xslt 工具一起使用。我做了一些非常简单的实现选择。例如,根节点始终称为“根”,数组进入带有 li 子元素的 ol 节点(如在 html 中),其他一切都只是具有原始值或另一个对象节点的子节点。

                            JsonXmlConverter.java

                            用法: JsonObject sampleJson = sampleJson(); org.w3c.dom.Document domNode = JsonXmlConverter.getW3cDocument(sampleJson, "root");

                            【讨论】:

                              【解决方案21】:

                              一种尚未给出的方法是使用解析器生成器在 XSLT 中创建解析器,该解析器解析 JSON 并生成 XML 输出。

                              在 XML 会议上经常提到的一个选项是 ReX 解析器生成器 (http://www.bottlecaps.de/rex/) - 虽然在网站上完全没有记录,但可以通过搜索获得食谱。

                              【讨论】:

                                【解决方案22】:

                                可以将 XSLT 与 JSON 一起使用。 XPath(3.1) XSLT(3.0) 和 XQuery(3.1) 的第 3 版以某种方式支持 JSON。 这似乎在 Saxon 的商业版本中可用,并且可能在某些时候包含在 HE 版本中。 https://www.saxonica.com/html/documentation/functions/fn/parse-json.html

                                -

                                我对替代解决方案的期望:

                                我希望能够输入 JSON 以获取一组匹配的数据,并输出 JSON 或 TEXT。

                                访问任意属性并计算值

                                支持条件逻辑

                                我希望转换脚本在工具外部,基于文本,最好是常用语言。

                                可能的替代方案?

                                我想知道 SQL 是否是一个合适的替代方案。 https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server

                                如果替代工具可以处理 JSON 和 XML,那就太好了 https://docs.microsoft.com/en-us/sql/relational-databases/xml/openxml-sql-server

                                我还没有尝试将我使用的 XSLT 脚本转换为 SQL,或者还没有完全评估过这个选项,但我希望能尽快研究它。目前只是一些想法。

                                【讨论】:

                                  【解决方案23】:

                                  不太确定是否需要这样做,对我来说,缺乏工具表明缺乏需要。 JSON 最好作为对象处理(无论如何它在 JS 中完成的方式),并且您通常使用对象本身的语言进行转换(Java 用于从 JSON 创建的 Java 对象,对于 Perl、Python、Perl、c#、PHP 等也是如此在)。只需使用普通的赋值(或设置、获取)、循环等。

                                  我的意思是,XSLT 只是另一种语言,需要它的一个原因是 XML 不是对象表示法,因此编程语言的对象并不完全适合(分层 xml 模型和对象/结构之间的阻抗)。

                                  【讨论】:

                                  • Facebook 从 XML 转为 Json 后,我迫切需要一个这样的工具。
                                  • 你在想什么用例?是否能够以类似于将 XML 响应呈现为 HTML 的方式呈现 JSON 内容?还是有什么不同?
                                  • 我想知道以编程对象方式(w/循环、根据需要分支等)操作 JSON 转换与使用 XSLT 类型方法相比有多么容易,特别是在转换大量 JSON 对象和其中源 JSON 中的一些数据在目标 JSON 中的一些节点上/下移动(因此不仅仅是结构的直接副本),并说明源或目标 JSON 中的特定节点是 JSON 中对象数组的一部分,而另一个JSON(源/目标)不是。
                                  • 轻松是非常主观的,所以我怀疑很大程度上与一个人的习惯有关。
                                  • 虽然肯定需要 JSON 转换,但您是对的,它在很大程度上由 JS 满足。 :-) 但是你见过jq - lightweight and flexible command-line JSON processor 吗?特别是当 JS 不可用时。我会说转换比 JS 更容易和更直观。例如提取字段nameaddress,并将它们放入一个数组中:[.name, .address]
                                  猜你喜欢
                                  • 2013-08-15
                                  • 2014-05-20
                                  • 1970-01-01
                                  • 2023-01-25
                                  • 1970-01-01
                                  • 2017-09-01
                                  • 1970-01-01
                                  • 2011-08-19
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多