【问题标题】:Is there a more elegant way to pass a big object variable to jq?有没有更优雅的方式将大对象变量传递给 jq?
【发布时间】:2017-10-03 21:18:23
【问题描述】:

我有以下 JSON 输入要转换(数百个类似对象的数组):

[{
    "Nmarch\u00e9": "2013-90006",
    "SIRETMandataire": null,
    "LibelleEntiteMandataire": "R\u00e9gion Bretagne",
    "SIRETAcheteur": null,
    "LibelleAcheteur": null,
    "Nature": null,
    "Objet": "PBF Formation qualifiante 2013 Monteur en construction bois lot 4",
    "CodeCPV": null,
    "Type ": "Services",
    "Procedure": "MAPA - art 30 - au dessus des seuils",
    "CodePostalCommuneExecution": 35000.0,
    "NomCommuneExecution": "Rennes",
    "CodeINSEEExecution": null,
    "GranulariteINSEEExecution": null,
    "MillesimeMandatement": 2013,
    "DateNotification": "2013-10-01",
    "Montant mandate TTC": 245526,
    "Montant mandate HT": null,
    "Montant attribue TTC": 245526,
    "Montant attribue HT": null,
    "Date de cloture": null,
    "Duree": null,
    "SIRETContractant": 300599123,
    "DenominationSociale": "AFPA DIRECTION REGIONALE BRETAGNE",
    "Role": "Titulaire",
    "CodePostal": 35208,
    "Dpt ID ": 35,
    "D\u00e9partement": "Ille-et-Vilaine",
    "Commune": "RENNES",
    "Taille": "10 000 et plus",
    "Taille des entreprises par categorie officielle": "Grande entreprise",
    "Code NAF": 8559,
    "Libelle NAF": "ENSEIGNEMENT",
    "Libelle SBA": "Administration publique\/enseignement",
    "Libelle CCI": "Tertiaire non marchand",
    "geolocalisation": null
}
]

Procedure 中,我有很多无效值需要通过值映射来替换。因此,我想将一个 JSON 对象提供给我的 jq 转换,其中无效值作为键,正确值作为值:

 {
    "MAPA - art 28": "Procédure adaptée",
    "MAPA - art 30 - au dessus des seuils": "Procédure adaptée",
    "MAPA - art 30 - en dessous des seuils": "Procédure adaptée",
    "Proc. adaptée/allégée (art.28et30)": "Procédure adaptée",
    "Procédure adaptée (MAPA)": "Procédure adaptée",
    "Appel d'offre ouvert": "Appel d'offres ouvert",
    "appel d'offres ouvert": "Appel d'offres ouvert",
    "Appel d'offre ouvert (art.33)": "Appel d'offres ouvert",
    "Appel d'offre restreint": "Appel d'offres restreint",
    "Achat direct": "Marché négocié sans publicité ni mise en concurrence préalable",
    "Négocié avec pub (art.35I)": "Procédure négociée avec mise en concurrence préalable",
    "Procédure négociée après pub": "Procédure négociée avec mise en concurrence préalable",
    "Procédure négociée après pub.": "Procédure négociée avec mise en concurrence préalable",
    "Procédure négociée sans pub": "Marché négocié sans publicité ni mise en concurrence préalable",
    "Procédure négociée sans pub.": "Marché négocié sans publicité ni mise en concurrence préalable",
    "Marché négocié": "Marché négocié sans publicité ni mise en concurrence préalable",
    "marché négocié": "Marché négocié sans publicité ni mise en concurrence préalable",
    "Marché negocié": "Marché négocié sans publicité ni mise en concurrence préalable"
}

我想在我的 jq 转换文件中声明这个对象,但是我没有看到如何使用 bla as var 语法来声明一个带有外部数据的变量(理想情况下我想将它声明为一个文件)。因此,我最终使用了--argjson 命令行参数。

这可行(我得到带有替换值的 JSON 输出),但我希望我可以有一个更简洁的命令并使其更易于维护:

cat temp.json | jq --argjson procedures '{"MAPA - art 28":"Procédure adaptée","MAPA - art 30 - au dessus des seuils":"Procédure adaptée","MAPA - art 30 - en dessous des seuils":"Procédure adaptée","Proc. adaptée/allégée (art.28et30)":"Procédure adaptée","Procédure adaptée (MAPA)":"Procédure adaptée","Appel d\u0027offre ouvert":"Appel d\u0027offres ouvert","appel d\u0027offres ouvert":"Appel d\u0027offres ouvert","Appel d\u0027offre ouvert (art.33)":"Appel d\u0027offres ouvert","Appel d\u0027offre restreint":"Appel d\u0027offres restreint","Achat direct":"Marché négocié sans publicité ni mise en concurrence préalable","Négocié avec pub (art.35I)":"Procédure négociée avec mise en concurrence préalable","Procédure négociée après pub":"Procédure négociée avec mise en concurrence préalable","Procédure négociée après pub.":"Procédure négociée avec mise en concurrence préalable","Procédure négociée sans pub":"Marché négocié sans publicité ni mise en concurrence préalable","Procédure négociée sans pub.":"Marché négocié sans publicité ni mise en concurrence préalable","Marché négocié":"Marché négocié sans publicité ni mise en concurrence préalable","marché négocié":"Marché négocié sans publicité ni mise en concurrence préalable","Marché negocié":"Marché négocié sans publicité ni mise en concurrence préalable"}' -f jq-filter.jq

供您参考,这里是 jq-filter.jq:

{
  "$schema": "../../schémas/json/paquet.json",
  "marches" : [.[] | {
      id: ."Nmarché",
      acheteur: {
          id: .SIRETMandataire,
          nom: .LibelleEntiteMandataire
      },
      nature: .Nature,
      objet: .Objet,
      codeCPV: .CodeCPV,
      procedure: $procedures[.Procedure],
      lieuExecution: {
          code: ( .CodeINSEEExecution //.CodePostalCommuneExecution),
          nom: .NomCommuneExecution,
          typeCode: (if .CodeINSEEExecution != null  then "Code commune" elif .CodePostalCommuneExecution != null then "Code postal" else null end)
      },
      dateNotification: .DateNotification,
      montant: ."Montant Attribue HT",
      dureeMois: null,
      titulaires: {
          id: .SIRETContractant,
          denominationSociale: .DenominationSociale
      }
  }
  ]
}

【问题讨论】:

    标签: json linux jq


    【解决方案1】:

    您是否有不能使用--slurpfile or --argfile 的原因?

    --slurpfile 变量名文件名:

    此选项读取命名文件中的所有 JSON 文本,并将解析的 JSON 值的数组绑定到给定的全局变量。如果你用 --argfile foo bar 运行 jq,那么 $foo 在程序中是可用的,并且有一个数组,其元素对应于名为 bar 的文件中的文本。

    --argfile 变量名文件名:

    不要使用。请改用 --slurpfile。 (此选项类似于 --slurpfile,但当文件只有一个文本时,则使用该文本,否则使用文本数组,如 --slurpfile。)

    假设您将映射放入 procedures.json 并稍微更改过滤器:

      procedure: $procedures[0][.Procedure],
    

    然后你可以使用 --slurpfile:

    $ jq --slurpfile procedures procedures.json -f jq-filter.jq temp.json
    

    或者你使用 --argfile (尽管文档说不要)

    $ jq --argfile procedures procedures.json -f jq-filter.jq temp.json
    

    无需对您的代码进行任何其他更改。

    【讨论】:

    • 嗨!那很快 :) 老实说,我不明白 slurpfile 是如何工作的,但我想是时候测试一下了。
    • 我刚刚在我的机器上尝试过它,它似乎按照记录的方式工作。我不太确定为什么文档说不要使用--argfile。它似乎也有效。
    • 太好了,我选择了 --slurpfile 选项。谢谢!
    • @jq170727 - 警告不要使用 --argfile 开关的作者很可能预计它最终会被删除,因为它的语义有点复杂。或者他只是想减少因为后者而产生的“错误报告”的洪流。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-25
    • 1970-01-01
    • 2017-02-22
    • 2011-06-13
    • 2014-10-03
    相关资源
    最近更新 更多