Create an array out of values extracted from a stream

Viewed 103

I am trying to use jq to formulate request parameters for an xhr.

The request must look like this:

{
  "ns:inputArticleItemList": {
    "#namespaces": {
      "ns": "http://www.unknown.com/ccp/basit/service/article/api"
    },
    "articles": [
      {
        "articleID": "000000000002158654",
        "insertCode": "62",
        "calculatePrice": true,
        "checkAvailability": true,
        "findExclusions": true
      },
      {
        "articleID": "000000000002147829",
        "insertCode": "62",
        "calculatePrice": true,
        "checkAvailability": true,
        "findExclusions": true
      },
      {
        "articleID": "000000000002103650",
        "insertCode": "62",
        "calculatePrice": true,
        "checkAvailability": true,
        "findExclusions": true
      },
    ]
  }
}

My JSON to work with comes like this:

{
  "2201299": {
    "title": "this is the product description for article 2201299",
    "prop1": "value1",
    "prop2": "value2",
    "prop3": "value3"
  }
}
{
  "2240002": {
    "title": "this is the product description for article 2240002",
    "prop1": "value1",
    "prop2": "value2",
    "prop3": "value3"
  }
}

So what I ideally want is the above to be transformed correctly. I see two difficulties here:

  1. the article number is an "unknown" key
  2. the JSON result doesn't seem to be an array itself?

best jq syntax I could come up with is:

{ "#namespaces": { "ns": "http://www.unknown.com/ccp/basit/service/article/api" } } + (keys[]| { articleId: ., insertCode: "62", calculatePrice: true, checkAvailability: true, findExclusions: true } | { articles: . }) | { "ns:inputArticleItemList": . }

However that fails to make a real array from the keys and insert the root/parent elements correctly.

Here is the result:

{
  "ns:inputArticleItemList": {
    "#namespaces": {
      "ns": "http://www.unknown.com/ccp/basit/service/article/api"
    },
    "articles": {
      "articleId": "2201299",
      "insertCode": "62",
      "calculatePrice": true,
      "checkAvailability": true,
      "findExclusions": true
    }
  }
}
{
  "ns:inputArticleItemList": {
    "#namespaces": {
      "ns": "http://www.unknown.com/ccp/basit/service/article/api"
    },
    "articles": {
      "articleId": "2240002",
      "insertCode": "62",
      "calculatePrice": true,
      "checkAvailability": true,
      "findExclusions": true
    }
  }
}

Here is the jqplay to fiddle with: https://jqplay.org/s/4rGV-xU05p

2 Answers

You're looking for inputs.

With -n/--null-input option on the command line, this program produces the expected output.

{
  "ns:inputArticleItemList": {
    "#namespaces": {
      "ns": "http://www.unknown.com/ccp/basit/service/article/api"
    },
    "articles": [
      { 
        "articleID": (inputs | keys_unsorted[]),
        "insertCode": "62",
        "calculatePrice": true,
        "checkAvailability": true,
        "findExclusions": true
      }
    ]
  }
}

Online demo

You can merge the combine the inputs into an array using slurp mode (--slurp/-s) and the following program:

{
   "ns:inputArticleItemList": {
      "#namespaces": {
         "ns": "http://www.unknown.com/ccp/basit/service/article/api"
      },
      articles: [
         {
            "articleID": ( .[] | keys_unsorted[] ),
            "insertCode": "62",
            "calculatePrice": true,
            "checkAvailability": true,
            "findExclusions": true
         }
      ]
   }
}

jqplay

Using slurp mode is functionally equivalent to using [ inputs ] as the source of inputs with null input (--null-input/-n), presenting an alternative solution.

jqplay

Related