Свернуть json массивов в один массив с комбинированными значениями ключей - PullRequest
0 голосов
/ 25 февраля 2020

Я пытаюсь объединить несколько JSON массивов в один массив свернутых, как ключевые значения. Вот к чему я получил код:

[
  {
    "projectId": 35525710,
    "jobs": [
        {
          "targetLanguage": "zh_CN",
          "jobId": 35826845,
          "earlyAccessStatus": "NOT_STARTED"
        },
        {
          "targetLanguage": "pt_BR",
          "jobId": 35826846,
          "earlyAccessStatus": "IN_PROGRESS"
        },
        {
          "targetLanguage": "zh_CN",
          "jobId": 35826836,
          "earlyAccessStatus": "IN_PROGRESS"
        },
        {
          "targetLanguage": "pt_BR",
          "jobId": 35826837,
          "earlyAccessStatus": "IN_PROGRESS"
        }
      ]
   }
]

Желаемый результат будет: ( Отредактировано ниже для выбора другого маршрута )

[
  {
    "projectId": 35525710,
    "jobs": [
        {
           "targetLanguage": "zh_CN",
           "jobIds": [35826845,35826836],
           "earlyAccessStatus": ["NOT_STARTED","IN_PROGRESS"]
        },
        {
           "targetLanguage": "pt_BR",
           "jobIds": [35826846,35826837],
           "earlyAccessStatus": ["IN_PROGRESS"]
        }
     ] 
   }
]

Я не совсем уверен, что произойдет с дублированными значениями ключа .earlyAccessStatus, будь то ["IN_PROGRESS","IN_PROGRESS"] или ["IN_PROGRESS"]. Последнее удовлетворяет мои возможные потребности, которые заключаются в получении значения .targetLanguage для любого языка, чей единственный .earlyAccessStatus - ["IN_PROGRESS"].

Используя этот фильтр с параметром jq -r, я могу вытащить Значение .targetLanguage для любых языков, у которых только .earlyAccessStatus равно ["IN_PROGRESS"]. Любая помощь будет принята с благодарностью!

.[].jobs[] | select(.[] | .earlyAccessStatus == ["IN_PROGRESS"] ) | .[] | .targetLanguage

Обновление: вот как выглядит необработанный JSON до того, как я что-то манипулировал. Я не привязан к какому-либо конкретному c методу. Я пытаюсь собрать данные о проекте с различными заданиями и изолировать языки, для которых все связанные задания достигли определенного шага (целевой файл export1), как указано «IN_PROGRESS». Если у языка есть одно задание на другом шаге, как, например, в zh_CN ниже, то этот язык не готов и не должен проходить через фильтр.

Чтобы получить вывод выше, я сделал это насколько (с одним обновлением, сделанным для устранения избыточных массивов внутри «заданий», уже предложенных, и я заранее извиняюсь за любую попытку Франкенштейна по разделению строк, которую вы видите в команде jq):

. | [{"projectId": .projectId, 
    "jobs": [( .jobs[] | 
        { "targetLanguage": .targetLanguage, 
          "jobId": .jobId,
          "earlyAccessStatus": (.steps[] | select(.workflowStepName == "Target file export1") | .status) } )] }]

Raw JSON:

{
  "projectId": 35902499,
  "completionStatus": "IN_PROGRESS",
  "activity": "ACTIVE",
  "sourceLanguage": "en_US",
  "jobs": [
    {
      "jobId": 35902526,
      "completionStatus": "IN_PROGRESS",
      "targetLanguage": "pt_BR",
      "steps": [
        {
          "workflowStepName": "Project Intake and Quote Generation1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Translate1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Correct1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Segment greenification1",
          "status": "FINISHED",
          "autoStatus": "SUCCESS"
        },
        {
          "workflowStepName": "Target file export1",
          "status": "IN_PROGRESS"
        }
      ]
    },
    {
      "jobId": 35902516,
      "completionStatus": "IN_PROGRESS",
      "targetLanguage": "zh_CN",
      "steps": [
        {
          "workflowStepName": "Project Intake and Quote Generation1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Translate1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Correct1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Segment greenification1",
          "status": "FINISHED",
          "autoStatus": "SUCCESS"
        },
        {
          "workflowStepName": "Target file export1",
          "status": "IN_PROGRESS"
        }
      ]
    },
    {
      "jobId": 36433561,
      "completionStatus": "IN_PROGRESS",
      "targetLanguage": "pt_BR",
      "steps": [
        {
          "workflowStepName": "Project Intake and Quote Generation1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Translate1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Correct1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Segment greenification1",
          "status": "FINISHED",
          "autoStatus": "SUCCESS"
        },
        {
          "workflowStepName": "Target file export1",
          "status": "IN_PROGRESS"
        }
      ]
    },
    {
      "jobId": 36433560,
      "completionStatus": "IN_PROGRESS",
      "targetLanguage": "zh_CN",
      "steps": [
        {
          "workflowStepName": "Project Intake and Quote Generation1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Translate1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Correct1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Segment greenification1",
          "status": "FINISHED",
          "autoStatus": "SUCCESS"
        },
        {
          "workflowStepName": "Target file export1",
          "status": "IN_PROGRESS"
        }
      ]
    },
    {
      "jobId": 36433552,
      "completionStatus": "IN_PROGRESS",
      "targetLanguage": "pt_BR",
      "steps": [
        {
          "workflowStepName": "Project Intake and Quote Generation1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Translate1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Correct1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Segment greenification1",
          "status": "FINISHED",
          "autoStatus": "SUCCESS"
        },
        {
          "workflowStepName": "Target file export1",
          "status": "IN_PROGRESS"
        }
      ]
    },
    {
      "jobId": 36433551,
      "completionStatus": "IN_PROGRESS",
      "targetLanguage": "zh_CN",
      "steps": [
        {
          "workflowStepName": "Project Intake and Quote Generation1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Translate1",
          "status": "FINISHED"
        },
        {
          "workflowStepName": "Correct1",
          "status": "IN_PROGRESS"
        },
        {
          "workflowStepName": "Segment greenification1",
          "status": "NOT_STARTED"
        },
        {
          "workflowStepName": "Target file export1",
          "status": "NOT_STARTED"
        }
      ]
    }
  ]
}

Новый подход

Сага продолжается. Я так близко подошел, выбрав другой маршрут.

.[].jobs | 
    map({targetLanguage: .targetLanguage, 
        earlyAccess: {
            jobId: .jobId, 
            earlyAccessStatus: .earlyAccessStatus}}) 
        | group_by(.targetLanguage) 
        | map({targetLanguage: .[0].targetLanguage, 
            jobId: map(.jobId) | unique, 
            earlyAccessStatus: map(.earlyAccessStatus) | unique})

Это дает мне в основном именно тот вывод, который я хочу, за исключением недостающих данных, которые мне нужны, что, я полагаю, является неудачей:

[
  {
    "targetLanguage": "pt_BR",
    "jobId": [
      null
    ],
    "earlyAccessStatus": [
      null
    ]
  },
  {
    "targetLanguage": "zh_CN",
    "jobId": [
      null
    ],
    "earlyAccessStatus": [
      null
    ]
  }
]

В идеале, вместо этого это вывело бы уникальные значения, содержащиеся в ключах jobId и earlyAccessStatus, например:

[
  {
    "targetLanguage": "pt_BR",
    "jobId": [
      35826846, 35826837
    ],
    "earlyAccessStatus": [
      "IN_PROGRESS"
    ]
  },
  {
    "targetLanguage": "zh_CN",
    "jobId": [
      35826845, 35826836
    ],
    "earlyAccessStatus": [
      "IN_PROGRESS", "NOT_STARTED"
    ]
  }
]

Это позволило бы мне легко фильтровать targetLanguage согласно earlyAccessStatus == ["IN_PROGRESS"].

Ответы [ 3 ]

0 голосов
/ 25 февраля 2020

Возможно, вы захотите переосмыслить все эти массивы внутри массивов, но следующее достигает того, что вы хотите, за исключением, возможно, упорядочения групп и ключей:

# meld all the objects in the given stream of objects
def meld(objects): 
  reduce objects as $o ({}; 
    reduce ($o|keys[]) as $k (.; .[$k] += [$o[$k]]));


.[0].jobs |=
  (group_by(.[0].targetLanguage)
   | map( [meld(.[] | .[0] ) | .targetLanguage |= .[0] ] ))

Это приводит к выводу показано ниже. Самый простой способ удалить дубликаты - добавить unique, например, как последний шаг в функции meld.

Аналогично, если вы хотите, чтобы группы упорядочивались по-разному, вы можете указать порядок как сообщение. -процесс обработки или напишите свой group_by.

Вывод

[
  {
    "projectId": 35525710,
    "jobs": [
      [
        {
          "earlyAccessStatus": [
            "IN_PROGRESS",
            "IN_PROGRESS"
          ],
          "jobId": [
            35826846,
            35826837
          ],
          "targetLanguage": "pt_BR"
        }
      ],
      [
        {
          "earlyAccessStatus": [
            "NOT_STARTED",
            "IN_PROGRESS"
          ],
          "jobId": [
            35826845,
            35826836
          ],
          "targetLanguage": "zh_CN"
        }
      ]
    ]
  }
]
0 голосов
/ 27 февраля 2020

понял что-то, что сработало! Больше пошли маршрут group_by и уникального.

. | [{projectId: .projectId, 
      jobs: [( .jobs[] | { 
            targetLanguage: .targetLanguage, 
            jobId: .jobId, 
            earlyAccessStatus: (.steps[] | select(.workflowStepName == "Target file export1") | .status), 
            finalStatus: (.steps[] | select(.workflowStepName == "Target file export2") | .status) } )] }] | 
      .[].jobs | group_by(.targetLanguage) | map({
            targetLanguage: .[0].targetLanguage, 
            jobId: map(.jobId),
            earlyAccessStatus: map(.earlyAccessStatus) | unique, 
            finalStatus: map(.finalStatus) | unique})

Этот метод работает в два этапа, сначала извлекая соответствующие данные и упорядочивая их следующим образом:

[
  {
    "projectId": 35525710,
    "jobs": [
        {
          "targetLanguage": "zh_CN",
          "jobId": 35826845,
          "earlyAccessStatus": "NOT_STARTED"
        },
        {
          "targetLanguage": "pt_BR",
          "jobId": 35826846,
          "earlyAccessStatus": "IN_PROGRESS"
        },
        {
          "targetLanguage": "zh_CN",
          "jobId": 35826836,
          "earlyAccessStatus": "IN_PROGRESS"
        },
        {
          "targetLanguage": "pt_BR",
          "jobId": 35826837,
          "earlyAccessStatus": "IN_PROGRESS"
        }
      ]
   }
]

Как только содержимое было упрощенный таким образом, он группируется по .targetLanguage, а затем ключи .jobId, .earlyAccessStatus и .finalStatus отображаются для их уникальных значений в каждой паре ключ-значение .targetLanguage. Я уверен, что есть более простой способ отформатировать это, но он выполняет именно то, что я намеревался выполнить sh, оставляя данные в этом формате:

[
  {
    "targetLanguage": "pt_BR",
    "jobId": [
      35902526,
      36433561,
      36433552
    ],
    "earlyAccessStatus": [
      "IN_PROGRESS"
    ],
    "finalStatus": [
      "IN_PROGRESS"
    ]
  },
  {
    "targetLanguage": "zh_CN",
    "jobId": [
      35902516,
      36433560,
      36433551
    ],
    "earlyAccessStatus": [
      "IN_PROGRESS",
      "NOT_STARTED"
    ],
    "finalStatus": [
      "IN_PROGRESS"
    ]
  }
]
0 голосов
/ 25 февраля 2020

Все эти одноэлементные длинные массивы - это боль, и я уверен, что есть лучший способ сделать это, но работает следующее:

jq '[.[]
     | .jobs |=
       [flatten
        | group_by(.targetLanguage)
        | .[]
        | [reduce .[] as $job ({jobId:[], earlyAccessStatus:[]};
             {targetLanguage: $job.targetLanguage,
              jobId: (.jobId + [$job.jobId]),
              earlyAccessStatus: (.earlyAccessStatus + [$job.earlyAccessStatus])})]
        | walk(if type == "object" and has("earlyAccessStatus")
               then .earlyAccessStatus |= unique
               else . end) ] ]' input.json
[
  {
    "projectId": 35525710,
    "jobs": [
      [
        {
          "targetLanguage": "pt_BR",
          "jobId": [
            35826846,
            35826837
          ],
          "earlyAccessStatus": [
            "IN_PROGRESS"
          ]
        }
      ],
      [
        {
          "targetLanguage": "zh_CN",
          "jobId": [
            35826845,
            35826836
          ],
          "earlyAccessStatus": [
            "IN_PROGRESS",
            "NOT_STARTED"
          ]
        }
      ]
    ]
  }
]
...