XSLT equivalente para JSON [fechado]

411

Existe um equivalente XSLT para JSON? Algo para me permitir fazer transformações no JSON, como o XSLT faz no XML.

luvieere
fonte
1
Btw, em que idioma / plataforma isso seria?
precisa saber é o seguinte
6
O @StaxMan XSLT é um padrão que possui implementações reais em muitos idiomas e plataformas. Minhas perguntas têm como objetivo um empreendimento semelhante.
Luvieere
36
+1 para sua pergunta. Muitas pessoas parecem ignorar ou simplesmente não gostam do XSLT, mas pode ser simplesmente uma reação à verbosidade do XML. E, de fato, como o XML cai gradualmente em desuso, há cada vez menos oportunidades para usar o XSLT, o que é uma pena! Um equivalente XSLT para JSON seria incrível.
Nicolas Le Thierry d'Ennequin
10
@ NicolasLeThierryd'Ennequin concordou. Muitas pessoas odeiam XML e, portanto, descartam o XSLT. O ecossistema XML de ferramentas também é pesado para desenvolvedores Java, o que afasta ainda mais pessoas. Mas eu estava muito interessado no XSLT em meados dos anos 2000 e há um poder tremendo que não tem equivalente direto fora do ecossistema XML. Eu adoraria um equivalente JSON!
Zearin 27/06

Respostas:

77

Idéia interessante. Algumas pesquisas no Google produziram algumas páginas de interesse, incluindo:

Espero que isto ajude.

Tim
fonte
10
Sim, obrigado, era o que eu estava procurando. É uma pena que a técnica não seja mais popular, o JSON é frequentemente usado como um formato de retorno nos serviços no estilo REST e seria bom ter uma maneira padrão de implementar transformações.
Luvieere 24/10/09
8
Este código usa string.eval () ... :-(
dreftymac
Resposta apenas do link
Jean-François Fabre
102

Equivalentes XSLT para JSON - uma lista de candidatos (ferramentas e especificações)

Ferramentas

  1. XSLT

    Você pode usar o XSLT para JSON com o objetivo de fn: json-to-xml .

    Esta seção descreve os recursos que permitem que dados JSON sejam processados ​​usando XSLT.

  2. jq

    O jq é como sed para dados JSON - você pode usá-lo para cortar, filtrar, mapear e transformar dados estruturados com a mesma facilidade que sed, awk, grep e amigos permitem que você jogue com texto. Existem pacotes de instalação para sistemas operacionais diferentes.

  3. jj

    JJ é um utilitário de linha de comando que fornece uma maneira rápida e simples de recuperar ou atualizar valores de documentos JSON. É alimentado por GJSON e SJSON sob o capô.

  4. fx

    Ferramenta de processamento JSON da linha de comandos

    • Não precisa aprender nova sintaxe
    • JavaScript simples
    • Formatação e destaque
    • Binário autônomo
  5. jl

    jl ("JSON lambda") é uma linguagem funcional minúscula para consultar e manipular JSON.

  6. SOLAVANCO

    Biblioteca de transformação JSON para JSON escrita em Java, onde a "especificação" para a transformação é ela própria um documento JSON.

  7. gron

    Torne o JSON greppable! O gron transforma o JSON em atribuições discretas para facilitar o grep pelo que você deseja e ver o 'caminho' absoluto para ele. Facilita a exploração de APIs que retornam grandes bolhas de JSON, mas possuem documentação terrível.

  8. json

    json é uma ferramenta CLI rápida para trabalhar com JSON. É um script node.js de arquivo único sem deps externos (além do próprio node.js).

  9. json-e

    JSON-e é um sistema de parametrização de estrutura de dados para incorporar contexto em objetos JSON. A idéia central é tratar uma estrutura de dados como um "modelo" e transformá-la, usando outra estrutura de dados como contexto, para produzir uma estrutura de dados de saída.

  10. JSLT

    JSLT é uma linguagem de consulta e transformação completa para JSON. O design do idioma é inspirado em jq, XPath e XQuery.

  11. JSONata

    JSONata é uma linguagem leve de consulta e transformação para dados JSON. Inspirado na semântica do 'caminho do local' do XPath 3.1, ele permite que consultas sofisticadas sejam expressas em uma notação compacta e intuitiva.

  12. json-transforms Last Commit 1 de dez de 2017

    Fornece uma abordagem recursiva e de correspondência de padrões para transformar dados JSON. As transformações são definidas como um conjunto de regras que correspondem à estrutura de um objeto JSON. Quando ocorre uma correspondência, a regra emite os dados transformados, recorrendo opcionalmente para transformar objetos filho.

  13. jsawk Última confirmação 4 de março de 2015

    Jsawk é como awk, mas para JSON. Você trabalha com uma matriz de objetos JSON lidos a partir de stdin, filtra-os usando JavaScript para produzir uma matriz de resultados impressa em stdout.

  14. yate Última confirmação 13 de março de 2017

    Os testes podem ser usados ​​como docu https://github.com/pasaran/yate/tree/master/tests

  15. jsonpath-object-transform Última confirmação 18 de janeiro de 2017

    Puxa dados de um literal de objeto usando JSONPath e gera novos objetos com base em um modelo.

  16. Última confirmação de grampeamento Sep 16, 2013

    O grampeamento é uma biblioteca JavaScript que permite a formatação XSLT para objetos JSON. Em vez de usar um mecanismo de modelagem JavaScript e modelos de texto / html, o Stapling oferece a oportunidade de usar modelos XSLT - carregados de forma assíncrona com o Ajax e depois no lado do cliente em cache - para analisar suas fontes de dados JSON.

Especificações:

  • JsonPointer

    O ponteiro JSON define uma sintaxe de sequência para identificar um valor específico em um documento JavaScript Object Notation (JSON).

  • JsonPath

    As expressões JSONPath sempre se referem a uma estrutura JSON da mesma maneira que a expressão XPath é usada em combinação com um documento XML

  • JSPath

    O JSPath para JSON é como XPath para XML. "

  • JSONiq

    A principal fonte de inspiração por trás do JSONiq é o XQuery, que até agora provou ser uma linguagem de consulta produtiva e bem-sucedida para dados semiestruturados

jschnasse
fonte
2
Obrigado por sua postagem muito detalhada e útil. Para transformar o json de uma linha em um formato legível, o jq (nº 2 da sua lista) é para mim a melhor escolha. Obrigado novamente!
primehunter
1
Costumo usar json_pp para uma boa impressão. Está disponível para muitas distribuições.
Jschnasse 15/03/19
70

Tente JOLT . É uma biblioteca de transformação JSON para JSON escrita em Java.

Ele foi criado especificamente porque não queríamos jogar o jogo "JSON -> XML -> XSLT -> XML -> JSON", e o uso de um modelo para qualquer transformação suficientemente complexa não é sustentável.

Milo S
fonte
4
+9000: Este é um projeto sério! Huzzah. A demo online com exemplos ajuda muito a subir a curva de aprendizagem: jolt-demo.appspot.com
kevinarpe
15

jq - processador JSON de linha de comando leve e flexível

Não é baseado em modelo como o XSLT, mas mais conciso. por exemplo, para extrair namee addresscampos em uma matriz:[.name, .address]

O tutorial mostra um exemplo de transformação da API JSON do Twitter (e o manual tem muitos exemplos).

13ren
fonte
4
É mais conciso porque é capaz de muito menos.
Ihe Onwuka
I não encontrou como pesquisar recursivamente um determinado atributo em uma árvore Json
Daniel
@Daniel é o .. | .attr_name?que você está procurando? (de stedolan.github.io/jq/manual/#RecursiveDescent: .. )
ankostis
1
Talvez não tão capaz como XSLT, mas muito útil e não tão complicado como XSLT
FLQ
15

O XSLT suporta JSON como visto em http://www.w3.org/TR/xslt-30/#json

XML usa colchetes angulares para tokens de delimitador, JSON usa colchetes, colchetes, ... I. e. As menos comparações de reconhecimento de token do XML significam que ele é otimizado para transformação declarativa, enquanto que mais comparações, como a instrução switch, por motivos de velocidade, pressupõem a previsão de ramificação especulativa para a qual o código imperativo nas linguagens de script é útil. Como conseqüência direta, para diferentes combinações de dados semiestruturados, convém comparar o desempenho dos mecanismos XSLT e javascript como parte das páginas responsivas. Para carga útil insignificante de dados, as transformações podem funcionar tão bem com JSON sem serialização XML. A decisão do W3 deve ser baseada em uma melhor análise.

Chawathe Vipul S
fonte
15

Recentemente, encontrei uma ferramenta que adoro para estilizar o JSON: https://github.com/twigkit/tempo . Ferramenta muito fácil de usar - na minha opinião, é muito mais fácil trabalhar com o XSLT - sem a necessidade de consultas XPATH.

Derek Curtis
fonte
9
O andamento fica ótimo se o resultado final da transformação for HTML. Mas e se você quiser apenas reorganizar uma estrutura implícita em outra, ainda assim o resultado final ainda é JSON. Eu ainda gostaria de ter um análogo do XPath para poder escrever a transformação de maneira funcional.
Toddius Zho 7/13
1
Tempo é realmente muito interessante, obrigado. No entanto, você pode enviar um xml para o navegador e um xslt (<? Xsl-stylesheet>) e seu navegador aplicará o xslt ao xml, mostrando uma visualização definida do seu xml sem nenhum código adicional. Esse também deve ser o caso do jsonT / tempo.
Martin Meeser
11

Dizer que a falta de ferramentas sugere que a falta de necessidade está apenas implorando a pergunta. O mesmo poderia ser aplicado ao suporte para X ou Y no Linux (por que se preocupar em desenvolver drivers e / ou jogos de qualidade para um sistema operacional tão minoritário? E por que prestar atenção em um sistema operacional para o qual as grandes empresas de jogos e hardware não desenvolvem?). Provavelmente, as pessoas que precisariam usar XSLT e JSON acabariam usando uma solução alternativa um tanto trivial: Transformando JSON em XML. Mas essa não é a solução ideal, é?

Quando você tem um formato JSON nativo e deseja editá-lo "wysywyg" no navegador, o XSLT seria uma solução mais que adequada para o problema. Fazer isso com a programação javascript tradicional pode se tornar um problema.

Na verdade, eu implementei uma abordagem da "idade da pedra" do XSLT, usando a análise de substring para interpretar alguns comandos básicos de javascript, como chamar um modelo, processar filhos, etc. Certamente, implementar um mecanismo de transformação com um objeto JSON é muito mais fácil do que implementando um analisador XML completo para analisar o XSLT. O problema é que, para usar modelos XML para transformar um objeto JSON, é necessário analisar o XML dos modelos.

Para transformar um objeto JSON com XML (ou HTML, ou texto ou o que for), você precisa pensar cuidadosamente sobre a sintaxe e quais caracteres especiais você precisa usar para identificar os comandos de transformação. Caso contrário, você precisará criar um analisador para sua própria linguagem de modelos personalizada. Tendo percorrido esse caminho, posso dizer que não é bonito.

Atualização (12 de novembro de 2010): Após algumas semanas trabalhando no meu analisador, consegui otimizá-lo. Os modelos são analisados ​​previamente e os comandos são armazenados como objetos JSON. As regras de transformação também são objetos JSON, enquanto o código do modelo é uma mistura de HTML e uma sintaxe de homebrew semelhante ao código do shell. Consegui transformar um documento JSON complexo em HTML para criar um editor de documentos. O código tem cerca de 1K linhas para o editor (é para um projeto privado, então não posso compartilhá-lo) e cerca de 990 linhas para o código de transformação JSON (inclui comandos de iteração, comparações simples, chamada de modelo, economia e avaliação de variáveis). Eu pretendo liberá-lo sob uma licença do MIT. Envie-me um e-mail se você quiser se envolver.

Rick
fonte
11

Eu escrevi minha própria pequena biblioteca em torno disso, recentemente, que tenta ficar o mais próximo possível

5.1 Modelo de processamento (XSLT REC) https://www.w3.org/TR/xslt#section-Processing-Model

quanto possível (como eu poderia de qualquer maneira), em algumas linhas de código JavaScript.

Aqui estão alguns exemplos de uso não completamente triviais ...

1. JSON para alguma marcação:

Fiddle: https://jsfiddle.net/YSharpLanguage/kj9pk8oz/10

(inspirado no Exemplo de documento D.1 (XSLT REC) https://www.w3.org/TR/xslt#section-Document-Example )

onde isso:

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));

... dá:

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

e

2. JSON para JSON:

Fiddle: https://jsfiddle.net/YSharpLanguage/ppfmmu15/10

onde isso:

// (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));

... dá:

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

3. XSLT vs. JavaScript:

Um equivalente a JavaScript de ...

Seção 14.4 do XSLT 3.0 REC Exemplo: agrupando nós com base em valores comuns

(em: http://jsfiddle.net/YSharpLanguage/8bqcd0ey/1 )

Cf. https://www.w3.org/TR/xslt-30/#grouping-examples

Onde...

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)
           });
    })
  );

... dá:

<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 vs. JavaScript:

Um equivalente a JavaScript de ...

Casos de uso JSONiq Seção 1.1.2. Agrupando consultas para JSON

(em: https://jsfiddle.net/YSharpLanguage/hvo24hmk/3 )

Cf. http://jsoniq.org/docs/JSONiq-usecases/html-single/index.html#jsongrouping

Onde...

/*
  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()

... dá:

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

Também é útil superar as limitações do JSONPath wrt. consulta contra o eixo ancestral, conforme levantado por essa pergunta do SO (e certamente outros).

Por exemplo, como obter o desconto de um item de supermercado sabendo seu ID de marca, em

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

?

Uma solução possível é:

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);

... que dá:

Discount of #983: 20

«HTH,

YSharp
fonte
10

Existe agora! Recentemente, criei uma biblioteca, json-transforma , exatamente para esse fim:

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

Ele usa uma combinação de JSPath , uma DSL modelada no XPath e uma abordagem de correspondência de padrão recursiva, inspirada diretamente no XSLT.

Aqui está um exemplo rápido. Dado o seguinte objeto 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 }
  ]
};

Aqui está uma transformação:

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);

Que produz o seguinte:

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

Essa transformação é composta por três regras. O primeiro corresponde a qualquer automóvel fabricado pela Honda, emitindo um objeto com uma Hondapropriedade e depois correspondendo recursivamente. A segunda regra corresponde a qualquer objeto com uma makerpropriedade, gerando as propriedades modele year. A final é a transformação de identidade que corresponde recursivamente.

ColinE
fonte
9

Como mais uma nova resposta para uma pergunta antiga, sugiro uma olhada no DefiantJS . Não é um equivalente XSLT para JSON, é XSLT para JSON. A seção "Templating" da documentação inclui este exemplo:

<!-- 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>
LS
fonte
5

Estou muito cansado da enorme quantidade de mecanismos de modelagem de JavaScript disponíveis no mercado e de todos os seus modelos HTML embutidos, diferentes estilos de marcação etc., e decidi construir uma pequena biblioteca que permite a formatação XSLT para estruturas de dados JSON. Não é ciência de foguetes de qualquer forma - é apenas JSON analisado em XML e formatado com um documento XSLT. Também é rápido, não tão rápido quanto os mecanismos de modelo JavaScript no Chrome, mas na maioria dos outros navegadores é pelo menos tão rápido quanto a alternativa do mecanismo JS para estruturas de dados maiores.

Björn
fonte
4

Estou usando a rota Camel umarshal (xmljson) -> para (xlst) -> marshal (xmljson). Eficiente o suficiente (embora não seja 100% perfeito), mas simples, se você já estiver usando o Camel.

Ben Goldin
fonte
3

O JSONiq é um padrão e o Zorba, uma implementação C ++ de código aberto. O JSONiq também pode ser visto como XQuery com a adição do JSON como um tipo de dados nativo.

mb21
fonte
2

O Yate ( https://github.com/pasaran/yate ) foi desenvolvido especificamente após o XSLT, apresenta o JPath (um equivalente XPath natural para JS), compila para JavaScript e tem um histórico de uso da produção. É praticamente indocumentado, mas a leitura de amostras e testes deve ser suficiente.

K Lee
fonte
2

O JSLT está muito próximo de um equivalente JSON do XSLT. É uma linguagem de transformação na qual você escreve a parte fixa da saída na sintaxe JSON e insere expressões para calcular os valores que deseja inserir no modelo.

Um exemplo:

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

É implementado em Java em cima de Jackson.

Lars Marius Garshol
fonte
0

Não tenho muita certeza da necessidade disso, e para mim a falta de ferramentas sugere falta de necessidade. O JSON é melhor processado como objetos (da mesma forma que é feito em JS), e você normalmente usa a linguagem dos próprios objetos para fazer transformações (objetos Java para Java criados a partir de JSON, o mesmo para Perl, Python, Perl, c #, PHP e assim por diante). em). Apenas com atribuições normais (ou definir, obter), repetir e assim por diante.

Quero dizer, XSLT é apenas outra linguagem, e uma razão pela qual é necessário é que XML não é uma notação de objeto e, portanto, objetos de linguagens de programação não são ajustes exatos (impedância entre o modelo xml hierárquico e os objetos / estruturas).

StaxMan
fonte
Depois que o Facebook foi convertido de XML para Json, preciso desesperadamente de uma ferramenta como essa.
Joe Soul-bringer
Em que caso de uso você está pensando? É possível renderizar o conteúdo JSON semelhante ao que você renderizaria respostas XML como HTML? Ou algo diferente?
StaxMan
Eu me pergunto como seria fácil manipular a transformação JSON da maneira programática do objeto (com loop, ramificação conforme necessário etc.) vs usando o método do tipo XSLT, particularmente no caso de transformar objetos JSON maciços e onde alguns dados na origem JSON são alterados up / down alguns nós no JSON de destino (portanto, não apenas uma cópia direta da estrutura) e diga onde um nó específico no JSON de origem ou destino faz parte da matriz de objetos no JSON e o outro JSON (origem / destino) não é .
David
A facilidade é muito subjetiva, então suspeito que muito disso tenha a ver com o que estamos acostumados.
StaxMan
Embora definitivamente seja necessário transformar o JSON, você está certo de que o JS é amplamente atendido. :-) Mas você viu jq - processador JSON de linha de comando leve e flexível ? Especialmente para quando o JS não estiver disponível. Eu diria que a transformação é muito mais fácil e intuitiva, mesmo que JS. por exemplo, para extrair os campos namee address, e colocá-los em uma matriz:[.name, .address]
13ren
0

Por que você não converte JSON em XML usando o Mr. Data Coverter , transforma-o usando XSLT e depois o altera novamente para JSON usando o mesmo.

user1058322
fonte
1
Essa não é uma opção se você deseja que seu código faça isso por você com bom desempenho.
orad
0

Para obter um doodle / prova de conceito de uma abordagem para utilizar JavaScript puro, juntamente com o padrão familiar e declarativo por trás das expressões correspondentes e dos modelos recursivos do XSLT, consulte https://gist.github.com/brettz9/0e661b3093764f496e36

(Uma abordagem semelhante pode ser adotada para JSON.)

Observe que a demonstração também conta com o fechamento da expressão JavaScript 1.8 por conveniência na expressão de modelos no Firefox (pelo menos até que o formato abreviado de ES6 para métodos possa ser implementado).

Isenção de responsabilidade: Este é o meu próprio código.

Brett Zamir
fonte
0

Eu escrevi um adaptador dom para minha estrutura de processamento de json baseada em jackson há muito tempo. Ele usa a biblioteca nu.xom. A árvore dom resultante funciona com os recursos java xpath e xslt. Fiz algumas escolhas de implementação bastante simples. Por exemplo, o nó raiz é sempre chamado de "raiz", as matrizes entram em um nó ol com subelementos li (como em html) e todo o resto é apenas um subnó com um valor primitivo ou outro nó de objeto.

JsonXmlConverter.java

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

Jilles van Gurp
fonte
0

Uma abordagem ainda não fornecida é usar um gerador de analisador para criar um analisador no XSLT que analisa JSON e produz uma saída XML.

Uma opção mencionada muito nas conferências XML é o gerador de analisador ReX ( http://www.bottlecaps.de/rex/ ) - embora totalmente indocumentado no site, as receitas estão disponíveis na pesquisa.

Tom Hillman
fonte
0

Pode ser possível usar o XSLT com JSON. O Verson 3 do XPath (3.1) XSLT (3.0) e XQuery (3.1) suporta JSON de alguma forma. Isso parece estar disponível na versão comercial do Saxon e pode em algum momento ser incluído na versão HE. https://www.saxonica.com/html/documentation/functions/fn/parse-json.html

-

O que eu esperaria de uma solução alternativa:

Gostaria de poder inserir o JSON para buscar um conjunto de dados correspondente e gerar JSON ou TEXT.

Acesse propriedades arbitrárias e avalie os valores

Suporte para lógica condicional

Eu gostaria que os scripts de transformação fossem externos à ferramenta, com base em texto e, de preferência, uma linguagem comumente usada.

Alternativa potencial?

Gostaria de saber se o SQL poderia ser uma alternativa adequada. https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server

Seria bom se a ferramenta alternativa pudesse lidar com JSON e XML https://docs.microsoft.com/en-us/sql/relational-databases/xml/openxml-sql-server

Ainda não tentei converter os scripts XSLT que uso em SQL ou avaliei completamente essa opção ainda, mas espero analisá-la mais em breve. Apenas alguns pensamentos até agora.

Onceler
fonte