ChatGPT解决这个技术问题 Extra ChatGPT

JSON 的 XSLT 等效项

JSON 是否有 XSLT 等价物?允许我对 JSON 进行转换,例如 XSLT 对 XML 的转换。

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

C
Community

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 脚本(除了 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 格式。与使用 JavaScript 模板引擎和 text/html 模板不同,Stapling 让您有机会使用 XSLT 模板(通过 Ajax 异步加载,然后缓存客户端)来解析您的 JSON 数据源。

眼镜:

json指针

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

JsonPath

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

JS路径

JSON 的 JSPath 就像 XML 的 XPath。”

JSONiq

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


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

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

概述如何实现这种“jsonT”工具,以及一些下载

对该实现的一些讨论

一家可能已经实施了合适的东西的公司

希望这可以帮助。


是的,谢谢,这就是我要找的。遗憾的是该技术并没有更流行,JSON 经常被用作 REST 样式服务中的返回格式,如果有一种标准的方式来实现对它的转换,那就太好了。
仅链接回答
M
Milo S

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

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


+9000:这是一个严肃的项目!胡扎。带有示例的在线演示极大地有助于攀登学习曲线:jolt-demo.appspot.com
C
Chawathe Vipul S

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

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


1
13ren

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 复杂
j
jschnasse

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


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

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

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,


R
Rick

说缺乏工具表明缺乏需求只是在乞求问题。 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 许可下发布它。如果您想参与,请给我发邮件。


M
Mr. Lance E Sloan

作为对老问题的又一个新答案,我建议看一下 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>

不过,需要浏览器 dom 的 Oof 是个大问题。 (Puppeteer 在高负载 ETL 服务器中确实不是一个好的选择)
C
ColinE

现在有!我最近专门为此目的创建了一个库 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 属性。最后是递归匹配的恒等变换。


B
Björn

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


B
Ben Goldin

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


m
mb21

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


L
Lars Marius Garshol

JSLT 非常接近于 XSLT 的 JSON 等价物。它是一种转换语言,您可以在其中以 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 实现的。


A
Andriy Gerasika

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

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


K
K Lee

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


u
user1058322

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


如果你想让你的代码以良好的性能为你做这件事,那不是一个选择。
B
Brett Zamir

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

(可以对 JSON 采取类似的方法。)

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

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


J
Jilles van Gurp

很久以前,我为我的基于杰克逊的 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");


T
Tom Hillman

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

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


O
Onceler

可以将 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,或者还没有完全评估过这个选项,但我希望能尽快研究它。到目前为止只是一些想法。


S
StaxMan

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

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


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