diff --git a/README.md b/README.md
index 83613911..45a7d0d4 100644
--- a/README.md
+++ b/README.md
@@ -147,6 +147,7 @@ option.
- `--airport` enables the `airport -I` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/airport))
- `--airport-s` enables the `airport -s` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s))
- `--arp` enables the `arp` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/arp))
+- `--asciitable` enables the ASCII and Unicode table parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable))
- `--asciitable-m` enables the multi-line ASCII and Unicode table parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable_m))
- `--blkid` enables the `blkid` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/blkid))
- `--cksum` enables the `cksum` and `sum` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/cksum))
diff --git a/docs/parsers/asciitable.md b/docs/parsers/asciitable.md
new file mode 100644
index 00000000..8a4ced2a
--- /dev/null
+++ b/docs/parsers/asciitable.md
@@ -0,0 +1,97 @@
+[Home](https://kellyjonbrazil.github.io/jc/)
+
+
+# jc.parsers.asciitable
+
+jc - JSON Convert `asciitable` parser
+
+This parser converts ASCII and Unicode text tables with single-line rows.
+
+Column headers must be at least two spaces apart from each other and must
+be unique.
+
+For example:
+
+ ╒══════════╤═════════╤════════╕
+ │ foo │ bar │ baz │
+ ╞══════════╪═════════╪════════╡
+ │ good day │ │ 12345 │
+ ├──────────┼─────────┼────────┤
+ │ hi there │ abc def │ 3.14 │
+ ╘══════════╧═════════╧════════╛
+
+ or
+
+ +-----------------------------+
+ | foo bar baz |
+ +-----------------------------+
+ | good day 12345 |
+ | hi there abc def 3.14 |
+ +-----------------------------+
+
+ or
+
+ | foo | bar | baz |
+ |----------|---------|--------|
+ | good day | | 12345 |
+ | hi there | abc def | 3.14 |
+
+ or
+
+ foo bar baz
+ --------- -------- ------
+ good day 12345
+ hi there abc def
+
+ etc.
+
+Usage (cli):
+
+ $ cat table.txt | jc --asciitable
+
+Usage (module):
+
+ import jc
+ result = jc.parse('asciitable', asciitable_string)
+
+Schema:
+
+ [
+ {
+ "column_name1": string, # empty string is null
+ "column_name2": string # empty string is null
+ }
+ ]
+
+Examples:
+
+ $ asciitable | jc --asciitable -p
+ []
+
+ $ asciitable | jc --asciitable -p -r
+ []
+
+
+
+### parse
+
+```python
+def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
+```
+
+Main text parsing function
+
+Parameters:
+
+ data: (string) text data to parse
+ raw: (boolean) unprocessed output if True
+ quiet: (boolean) suppress warning messages if True
+
+Returns:
+
+ List of Dictionaries. Raw or processed structured data.
+
+### Parser Information
+Compatibility: linux, darwin, cygwin, win32, aix, freebsd
+
+Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
diff --git a/docs/parsers/asciitable_m.md b/docs/parsers/asciitable_m.md
index 8afd2e3d..7c416618 100644
--- a/docs/parsers/asciitable_m.md
+++ b/docs/parsers/asciitable_m.md
@@ -41,8 +41,8 @@ Schema:
[
{
- "column_name1": string,
- "column_name2": string
+ "column_name1": string, # empty string is null
+ "column_name2": string # empty string is null
}
]
diff --git a/jc/parsers/asciitable_m.py b/jc/parsers/asciitable_m.py
index c3f1c575..415fef0b 100644
--- a/jc/parsers/asciitable_m.py
+++ b/jc/parsers/asciitable_m.py
@@ -36,8 +36,8 @@ Schema:
[
{
- "column_name1": string,
- "column_name2": string
+ "column_name1": string, # empty string is null
+ "column_name2": string # empty string is null
}
]
@@ -92,7 +92,7 @@ Examples:
]
"""
import re
-from typing import Iterable, Tuple, List, Dict
+from typing import Iterable, Tuple, List, Dict, Optional
import jc.utils
from jc.exceptions import ParseError
@@ -350,11 +350,21 @@ def _collapse_data(table: List[List[List[str]]]) -> List[List[str]]:
return result
-def _create_table_dict(header: List[str], data: List[List[str]]) -> List[Dict[str, str]]:
- return [dict(zip(header, r)) for r in data]
+def _create_table_dict(header: List[str], data: List[List[str]]) -> List[Dict[str, Optional[str]]]:
+ """
+ zip the headers and data to create a list of dictionaries. Also convert
+ empty strings to None.
+ """
+ table_list_dict: List[Dict[str, Optional[str]]] = [dict(zip(header, r)) for r in data]
+ for row in table_list_dict:
+ for k, v in row.items():
+ if v == '':
+ row[k] = None
+
+ return table_list_dict
-def _parse_pretty(string: str) -> List[Dict[str, str]]:
+def _parse_pretty(string: str) -> List[Dict[str, Optional[str]]]:
string_lines: List[str] = string.splitlines()
clean: List[Tuple[int, List[str]]] = _normalize_rows(string_lines)
raw_headers: List[List[str]] = _get_headers(clean)
@@ -362,7 +372,7 @@ def _parse_pretty(string: str) -> List[Dict[str, str]]:
new_headers: List[str] = _collapse_headers(raw_headers)
new_data: List[List[str]] = _collapse_data(raw_data)
- final_table: List[Dict[str, str]] = _create_table_dict(new_headers, new_data)
+ final_table: List[Dict[str, Optional[str]]] = _create_table_dict(new_headers, new_data)
return final_table
diff --git a/man/jc.1 b/man/jc.1
index e29c47d6..7b642f1b 100644
--- a/man/jc.1
+++ b/man/jc.1
@@ -37,6 +37,11 @@ Parsers:
\fB--arp\fP
`arp` command parser
+.TP
+.B
+\fB--asciitable\fP
+ASCII and Unicode table parser
+
.TP
.B
\fB--asciitable-m\fP