mycroft-core/mycroft/util/json_helper.py

87 lines
2.4 KiB
Python

# Copyright 2017 Mycroft AI Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import json
def merge_dict(base, delta):
"""
Recursively merging configuration dictionaries.
Args:
base: Target for merge
delta: Dictionary to merge into base
"""
for k, dv in delta.items():
bv = base.get(k)
if isinstance(dv, dict) and isinstance(bv, dict):
merge_dict(bv, dv)
else:
base[k] = dv
def load_commented_json(filename):
""" Loads an JSON file, ignoring comments
Supports a trivial extension to the JSON file format. Allow comments
to be embedded within the JSON, requiring that a comment be on an
independent line starting with '//' or '#'.
NOTE: A file created with these style comments will break strict JSON
parsers. This is similar to but lighter-weight than "human json"
proposed at https://hjson.org
Args:
filename (str): path to the commented JSON file
Returns:
obj: decoded Python object
"""
with open(filename) as f:
contents = f.read()
return json.loads(uncomment_json(contents))
def uncomment_json(commented_json_str):
""" Removes comments from a JSON string.
Supporting a trivial extension to the JSON format. Allow comments
to be embedded within the JSON, requiring that a comment be on an
independent line starting with '//' or '#'.
Example...
{
// comment
'name' : 'value'
}
Args:
commented_json_str (str): a JSON string
Returns:
str: uncommented, legal JSON
"""
lines = commented_json_str.splitlines()
# remove all comment lines, starting with // or #
nocomment = []
for line in lines:
stripped = line.lstrip()
if stripped.startswith("//") or stripped.startswith("#"):
continue
nocomment.append(line)
return " ".join(nocomment)