Как получить последнюю пару ключ-значение даты из массива json, включая родительские ключи - PullRequest
2 голосов
/ 28 апреля 2019

1) Я пытаюсь сгенерировать файл CSV, используя jq из json.2) Мне нужны родительские ключи вместе с одной парой ключ-значение из дочернего массива. 3) У какого значения будет последняя дата, будет полученная пара ключ-значение. 4) Необходимо создать CSV из этого результата

.

Это мой json

{
    "students": [
        {
            "name": "Name1",
            "class": "parentClass1",
            "teacher": "teacher1",
            "attendance": [
                {
                    "key": "class1",
                    "value": "01-DEC-2018"
                },
                {
                    "key": "class1",
                    "value": "28-Nov-2018"
                },
                {
                    "key": "class1",
                    "value": "26-Oct-2018"
                }
            ]
        },
        {
            "name": "Name2",
            "class": "parentClass2",
            "teacher": "teacher2",
            "attendance": [
                {
                    "key": "class2",
                    "value": "05-DEC-2018"
                },
                {
                    "key": "class2",
                    "value": "25-Nov-2018"
                },
                {
                    "key": "class2",
                    "value": "20-Oct-2018"
                }
            ]
        }
    ]
}

Я не добился большого прогресса Я пытаюсь создать CSV, как это

jq  '.students[] | [.name, .class, attendance[].key,.properties[].value] | @csv ' main.json

Ниже ожидается CSV от этого json

Name         ParentClass        key         dateValue                                                                           Summary
Name1        parentClass1      class1       150 days ago(difference with today date with latest date i.e 01-DEC-2018 )         Teacher1.parentClass1
Name2        parentClass2      class2       150 days ago(difference with today date with latest date i.e 05-DEC-2018 )         Teacher2.parentClass2

Ответы [ 2 ]

3 голосов
/ 28 апреля 2019

Разобрать даты с помощью strptime и присвоить результат значению с, таким образом, вы можете получить самую последнюю посещаемость с помощью max_by.Преобразуйте значение в секунды с начала эпохи, используя mktime, вычтите его из сейчас , разделите на 24 * 60 * 60, чтобы получить число дней с тех пор.

$ jq -r '
def days_since:
  (now - .) / 86400 | floor;
.students[]
| [ .name, .class ] +
  ( .attendance
    | map(.value |= strptime("%d-%b-%Y"))
    | max_by(.value)
    | [ .key, "\(.value | mktime | days_since) days ago" ]
  ) +
  [ .teacher + "." + .class ]
| @tsv' file
Name1   parentClass1    class1  148 days ago    teacher1.parentClass1
Name2   parentClass2    class2  144 days ago    teacher2.parentClass2

Обратите внимание, что это решение не касается изменений летнего времени.

1 голос
/ 28 апреля 2019

Для производственных целей jq не может использоваться здесь, потому что это не позволяет выполнять расчеты даты на летнее время.

Я бы использовал Python, потому что он позволяет выполнять вычисления даты в летнее время, по умолчанию поставляется с поддержкой json и устанавливается практически на все производные UNIX.

#!/usr/bin/env python
import argparse
from datetime import datetime
import json


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('filename')
    return parser.parse_args()


def main():
    args = parse_args()
    with open(args.filename) as file_desc:
        data = json.load(file_desc)

    print('Name\tParentClass\tkey\tdateValue')

    today = datetime.today()
    for record in data['students']:
        for a in record['attendance']:
            date = datetime.strptime(a['value'], '%d-%b-%Y')
            a['since'] = (today - date).days
        last = sorted(record['attendance'], key=lambda x: x['since'])[0]
        print('\t'.join([
            record['name'],
            record['class'],
            last['key'],
            '{} days ago'.format(last['since']),
            '{}.{}'.format(record['teacher'], record['class']),
        ]))


if __name__ == '__main__':
    main()

Вывод (в день написания этого ответа):

Name    ParentClass Key DateValue   Summary
Name1   parentClass1    class1  148 days ago    teacher1.parentClass1
Name2   parentClass2    class2  144 days ago    teacher2.parentClass2
...