JsonhPy 2.3__tar.gz → 2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {jsonhpy-2.3 → jsonhpy-2.4}/PKG-INFO +1 -1
- {jsonhpy-2.3 → jsonhpy-2.4}/pyproject.toml +1 -1
- {jsonhpy-2.3 → jsonhpy-2.4}/src/JsonhPy/JsonhPy.py +127 -0
- {jsonhpy-2.3 → jsonhpy-2.4}/src/JsonhPy.egg-info/PKG-INFO +1 -1
- {jsonhpy-2.3 → jsonhpy-2.4}/LICENSE.md +0 -0
- {jsonhpy-2.3 → jsonhpy-2.4}/README.md +0 -0
- {jsonhpy-2.3 → jsonhpy-2.4}/setup.cfg +0 -0
- {jsonhpy-2.3 → jsonhpy-2.4}/src/JsonhPy/__init__.py +0 -0
- {jsonhpy-2.3 → jsonhpy-2.4}/src/JsonhPy.egg-info/SOURCES.txt +0 -0
- {jsonhpy-2.3 → jsonhpy-2.4}/src/JsonhPy.egg-info/dependency_links.txt +0 -0
- {jsonhpy-2.3 → jsonhpy-2.4}/src/JsonhPy.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import math
|
|
2
2
|
from enum import Enum
|
|
3
3
|
from typing import Iterator, Iterable
|
|
4
|
+
import json
|
|
4
5
|
|
|
5
6
|
class JsonhResult[T, E]:
|
|
6
7
|
is_error: bool
|
|
@@ -557,6 +558,132 @@ class JsonhReader:
|
|
|
557
558
|
|
|
558
559
|
return next_element
|
|
559
560
|
|
|
561
|
+
def parse_json(self, include_comments: bool = False, indent: str | None = None) -> JsonhResult[str, str]:
|
|
562
|
+
"""
|
|
563
|
+
Parses a single element as JSON from the reader.
|
|
564
|
+
|
|
565
|
+
If `include_comments` is true, comments are included (`/*` and `*/` are escaped as `/ *` and `* /`).
|
|
566
|
+
|
|
567
|
+
If `indent` is not null, the output is pretty-printed with the given indentation.
|
|
568
|
+
|
|
569
|
+
The result is not safe to embed in HTML.
|
|
570
|
+
"""
|
|
571
|
+
|
|
572
|
+
current_depth: int = 0
|
|
573
|
+
isStartOfStructure: bool = True
|
|
574
|
+
is_property_value: bool = False
|
|
575
|
+
|
|
576
|
+
resultBuilder: str = ""
|
|
577
|
+
|
|
578
|
+
for token_result in self.read_element():
|
|
579
|
+
# Check error
|
|
580
|
+
if (token_result.is_error):
|
|
581
|
+
return JsonhResult.from_error(token_result.error())
|
|
582
|
+
token: JsonhToken = token_result.value()
|
|
583
|
+
|
|
584
|
+
# Add comments and indents
|
|
585
|
+
if not is_property_value:
|
|
586
|
+
# Add comma before property/item
|
|
587
|
+
if (token.json_type not in [JsonTokenType.NONE, JsonTokenType.COMMENT]) and (current_depth > 0) and (not isStartOfStructure):
|
|
588
|
+
# Don't add trailing comma
|
|
589
|
+
if token.json_type not in [JsonTokenType.END_OBJECT, JsonTokenType.END_ARRAY]:
|
|
590
|
+
resultBuilder += ','
|
|
591
|
+
|
|
592
|
+
# Apply indentation
|
|
593
|
+
if indent != None:
|
|
594
|
+
# Don't indent inside empty structures
|
|
595
|
+
if not (token.json_type in [JsonTokenType.END_OBJECT, JsonTokenType.END_ARRAY] and isStartOfStructure):
|
|
596
|
+
# Don't indent comment if not included
|
|
597
|
+
if (not (token.json_type == JsonTokenType.COMMENT and (not include_comments))):
|
|
598
|
+
# Don't indent root elements
|
|
599
|
+
if current_depth > 0:
|
|
600
|
+
# Add newline before element
|
|
601
|
+
resultBuilder += '\n'
|
|
602
|
+
|
|
603
|
+
# Get current indent count
|
|
604
|
+
indent_count: int = current_depth
|
|
605
|
+
if token.json_type in [JsonTokenType.END_OBJECT, JsonTokenType.END_ARRAY]:
|
|
606
|
+
indent_count -= 1
|
|
607
|
+
|
|
608
|
+
# Add indent
|
|
609
|
+
for _ in range(0, indent_count):
|
|
610
|
+
resultBuilder += indent
|
|
611
|
+
# Track start of structure to avoid adding leading comma
|
|
612
|
+
if token.json_type not in [JsonTokenType.NONE, JsonTokenType.COMMENT]:
|
|
613
|
+
isStartOfStructure = False
|
|
614
|
+
if token.json_type in [JsonTokenType.START_OBJECT, JsonTokenType.START_ARRAY]:
|
|
615
|
+
isStartOfStructure = True
|
|
616
|
+
|
|
617
|
+
match token.json_type:
|
|
618
|
+
# Null
|
|
619
|
+
case JsonTokenType.NONE:
|
|
620
|
+
resultBuilder += "null"
|
|
621
|
+
if current_depth == 0:
|
|
622
|
+
return JsonhResult.from_value(resultBuilder)
|
|
623
|
+
# True
|
|
624
|
+
case JsonTokenType.TRUE:
|
|
625
|
+
resultBuilder += "true"
|
|
626
|
+
if current_depth == 0:
|
|
627
|
+
return JsonhResult.from_value(resultBuilder)
|
|
628
|
+
# False
|
|
629
|
+
case JsonTokenType.FALSE:
|
|
630
|
+
resultBuilder += "false"
|
|
631
|
+
if current_depth == 0:
|
|
632
|
+
return JsonhResult.from_value(resultBuilder)
|
|
633
|
+
# String
|
|
634
|
+
case JsonTokenType.STRING:
|
|
635
|
+
resultBuilder += json.dumps(token.value, ensure_ascii=False)
|
|
636
|
+
if current_depth == 0:
|
|
637
|
+
return JsonhResult.from_value(resultBuilder)
|
|
638
|
+
# Number
|
|
639
|
+
case JsonTokenType.NUMBER:
|
|
640
|
+
result: JsonhResult[float] = JsonhNumberParser.parse(token_result.value().value)
|
|
641
|
+
if (result.is_error):
|
|
642
|
+
return JsonhResult.from_error(result.error())
|
|
643
|
+
resultBuilder += str(result.value())
|
|
644
|
+
if current_depth == 0:
|
|
645
|
+
return JsonhResult.from_value(resultBuilder)
|
|
646
|
+
# Start Object
|
|
647
|
+
case JsonTokenType.START_OBJECT:
|
|
648
|
+
resultBuilder += '{'
|
|
649
|
+
current_depth += 1
|
|
650
|
+
# Start Array
|
|
651
|
+
case JsonTokenType.START_ARRAY:
|
|
652
|
+
resultBuilder += '['
|
|
653
|
+
current_depth += 1
|
|
654
|
+
# End Object
|
|
655
|
+
case JsonTokenType.END_OBJECT:
|
|
656
|
+
resultBuilder += '}'
|
|
657
|
+
current_depth -= 1
|
|
658
|
+
if current_depth == 0:
|
|
659
|
+
return JsonhResult.from_value(resultBuilder)
|
|
660
|
+
# End Array
|
|
661
|
+
case JsonTokenType.END_ARRAY:
|
|
662
|
+
resultBuilder += ']'
|
|
663
|
+
current_depth -= 1
|
|
664
|
+
if current_depth == 0:
|
|
665
|
+
return JsonhResult.from_value(resultBuilder)
|
|
666
|
+
# Property Name
|
|
667
|
+
case JsonTokenType.PROPERTY_NAME:
|
|
668
|
+
resultBuilder += json.dumps(token.value, ensure_ascii=False)
|
|
669
|
+
resultBuilder += ':'
|
|
670
|
+
if indent != None:
|
|
671
|
+
resultBuilder += ' '
|
|
672
|
+
# Comment
|
|
673
|
+
case JsonTokenType.COMMENT:
|
|
674
|
+
if (include_comments):
|
|
675
|
+
resultBuilder += "/*"
|
|
676
|
+
resultBuilder += token.value.replace("/*", "/ *").replace("*/", "* /")
|
|
677
|
+
resultBuilder += "*/"
|
|
678
|
+
# Not implemented
|
|
679
|
+
case _:
|
|
680
|
+
return JsonhResult.from_error("Token type not implemented")
|
|
681
|
+
|
|
682
|
+
is_property_value = token.json_type == JsonTokenType.PROPERTY_NAME
|
|
683
|
+
|
|
684
|
+
# End of input
|
|
685
|
+
return JsonhResult.from_error("Expected token, got end of input")
|
|
686
|
+
|
|
560
687
|
def find_property_value(self, property_name: str) -> bool:
|
|
561
688
|
"""
|
|
562
689
|
Tries to find the given property name in the reader.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|