From 46ebdfe074eb410968764f39b38b10ec145d3d13 Mon Sep 17 00:00:00 2001 From: Chris Berkhout Date: Mon, 4 Apr 2022 13:40:04 +0200 Subject: [PATCH] Add JSON and JSONL output formats. --- README.md | 8 +++-- src/pricehist/outputs/__init__.py | 3 ++ src/pricehist/outputs/json.py | 54 +++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 src/pricehist/outputs/json.py diff --git a/README.md b/README.md index 1e7f35a..05f6492 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ pipx install pricehist - **`beancount`**: [Beancount](http://furius.ca/beancount/) - **`csv`**: [Comma-separated values](https://en.wikipedia.org/wiki/Comma-separated_values) +- **`json`**: [JSON](https://en.wikipedia.org/wiki/JSON) +- **`jsonl`**: [JSON lines](https://en.wikipedia.org/wiki/JSON_streaming) - **`gnucash-sql`**: [GnuCash](https://www.gnucash.org/) SQL - **`ledger`**: [Ledger](https://www.ledger-cli.org/) and [hledger](https://hledger.org/) @@ -91,7 +93,7 @@ pricehist fetch -h ``` ``` usage: pricehist fetch SOURCE PAIR [-h] [-vvv] [-t TYPE] [-s DATE | -sx DATE] [-e DATE | -ex DATE] -[-o beancount|csv|gnucash-sql|ledger] [--invert] [--quantize INT] +[-o beancount|csv|json|jsonl|gnucash-sql|ledger] [--invert] [--quantize INT] [--fmt-base SYM] [--fmt-quote SYM] [--fmt-time TIME] [--fmt-decimal CHAR] [--fmt-thousands CHAR] [--fmt-symbol rightspace|right|leftspace|left] [--fmt-datesep CHAR] [--fmt-csvdelim CHAR] @@ -122,8 +124,8 @@ optional arguments: ### Choose and customize the output format -As the output format you can choose one of `beancount`, `csv`, `ledger` or -`gnucash-sql`. +As the output format you can choose one of `beancount`, `csv`, `json`, `jsonl`, +`ledger` or `gnucash-sql`. ``` pricehist fetch ecb EUR/AUD -s 2021-01-04 -e 2021-01-08 -o ledger diff --git a/src/pricehist/outputs/__init__.py b/src/pricehist/outputs/__init__.py index 98e9547..4b015c8 100644 --- a/src/pricehist/outputs/__init__.py +++ b/src/pricehist/outputs/__init__.py @@ -1,6 +1,7 @@ from .beancount import Beancount from .csv import CSV from .gnucashsql import GnuCashSQL +from .json import JSON from .ledger import Ledger default = "csv" @@ -8,6 +9,8 @@ default = "csv" by_type = { "beancount": Beancount(), "csv": CSV(), + "json": JSON(), + "jsonl": JSON(jsonl=True), "gnucash-sql": GnuCashSQL(), "ledger": Ledger(), } diff --git a/src/pricehist/outputs/json.py b/src/pricehist/outputs/json.py new file mode 100644 index 0000000..7e0f674 --- /dev/null +++ b/src/pricehist/outputs/json.py @@ -0,0 +1,54 @@ +""" +JSON output + +Date, number and base/quote formatting options will be respected. + +Classes: + + JSON + +""" + +import io +import json + +from pricehist.format import Format + +from .baseoutput import BaseOutput + + +class JSON(BaseOutput): + def __init__(self, jsonl=False): + self.jsonl = jsonl + + def format(self, series, source, fmt=Format()): + data = [] + output = io.StringIO() + + base = fmt.base or series.base + quote = fmt.quote or series.quote + + for price in series.prices: + date = fmt.format_date(price.date) + amount = fmt.format_num(price.amount) + + data.append( + { + "date": date, + "base": base, + "quote": quote, + "amount": amount, + "source": source.id(), + "type": series.type, + } + ) + + if self.jsonl: + for row in data: + json.dump(row, output) + output.write("\n") + else: + json.dump(data, output, indent=2) + output.write("\n") + + return output.getvalue()