【问题标题】:Cannot write dict object as correct JSON to file无法将 dict 对象作为正确的 JSON 写入文件
【发布时间】:2018-04-06 16:26:09
【问题描述】:

我尝试从文件中读取 JSON,获取值,转换它们并回写到新文件。

{
  "metadata": {
    "info": "important info"
  },
  "timestamp": "2018-04-06T12:19:38.611Z",
  "content": {
    "id": "1",
    "name": "name test",
    "objects": [
      {
        "id": "1",
        "url": "http://example.com",
        "properties": [
          {
            "id": "1",
            "value": "1"
          }
        ]
      }
    ]
  }
}

上面是我从文件中读取的 JSON。 下面我附上一个获取值、创建新 JSON 并将其写入文件的 python 程序。

import json
from pprint import pprint


def load_json(file_name):
    return json.load(open(file_name))


def get_metadata(json):
    return json["metadata"]


def get_timestamp(json):
    return json["timestamp"]


def get_content(json):
    return json["content"]


def create_json(metadata, timestamp, content):
    dct = dict(__metadata=metadata, timestamp=timestamp, content=content)
    return json.dumps(dct)

def write_json_to_file(file_name, json_content):
    with open(file_name, 'w') as file:
        json.dump(json_content, file)


STACK_JSON = 'stack.json';
STACK_OUT_JSON = 'stack-out.json'


if __name__ == '__main__':
    json_content = load_json(STACK_JSON)
    print("Loaded JSON:")
    print(json_content)

    metadata = get_metadata(json_content)
    print("Metadata:", metadata)
    timestamp = get_timestamp(json_content)
    print("Timestamp:", timestamp)
    content = get_content(json_content)
    print("Content:", content)

    created_json = create_json(metadata, timestamp, content)
    print("\n\n")
    print(created_json)

    write_json_to_file(STACK_OUT_JSON, created_json)

但问题是 create json 不正确。最后我得到了:

"{\"__metadata\": {\"info\": \"important info\"}, \"timestamp\": \"2018-04-06T12:19:38.611Z\", \"content\": {\"id\": \"1\", \"name\": \"name test\", \"objects\": [{\"id\": \"1\", \"url\": \"http://example.com\", \"properties\": [{\"id\": \"1\", \"value\": \"1\"}]}]}}"

这不是我想要达到的。这不是正确的 JSON。我错了什么?

【问题讨论】:

    标签: json python-3.x


    【解决方案1】:

    解决办法:

    像这样更改write_json_to_file(...) 方法:

    def write_json_to_file(file_name, json_content):
        with open(file_name, 'w') as file:
            file.write(json_content)
    

    解释:

    问题是,当您在脚本末尾调用write_json_to_file(STACK_OUT_JSON, created_json) 时,变量created_json 包含string - 它是在create_json(...) 函数中创建的字典的JSON 表示。但在write_json_to_file(file_name, json_content) 中,您正在调用:

    json.dump(json_content, file)
    

    您告诉json 模块将变量json_content(其中包含string)的JSON 表示形式写入文件中。 string 的 JSON 表示是封装在双引号 (") 中的单个值,其中包含的所有双引号都被 \ 转义。 您想要实现的是简单地将json_content 变量的值写入文件,而不是先对其进行 JSON 序列化。

    【讨论】:

    • 感谢您的回答!
    【解决方案2】:

    问题

    您将dict 转换为json,然后在将其写入文件之前,您再次将其转换为json。当您重试将json 转换为json 时,它会为您提供\",因为它正在转义",因为它假定您在那里有一个值。

    如何解决?

    读取json 文件,将其转换为dict 并对它执行各种操作是一个好主意。并且仅当您想打印输出或写入文件或返回转换为json 的输出时,因为json.dump() 很昂贵,它会增加2ms(大约)的开销,这可能看起来不多,但是当您的代码在500 microseconds 中运行几乎是 4 次。

    其他建议

    看到您的代码后,我意识到您来自java 背景,而在javagetThis()getThat() 是模块化代码的好方法,因为我们在@987654339 中表示我们的代码@ in java, in python 它只会导致PEP 8style guide for python中提到的代码的readability出现问题。

    我已经更新了下面的代码:

    import json
    
    
    def get_contents_from_json(file_path)-> dict:
        """
        Reads the contents of the json file into a dict
        :param file_path:
        :return: A dictionary of all contents in the file.
        """
        try:
            with open(file_path) as file:
                contents = file.read()
                return json.loads(contents)
        except json.JSONDecodeError:
            print('Error while reading json file')
        except FileNotFoundError:
            print(f'The JSON file was not found at the given path: \n{file_path}')
    
    
    def write_to_json_file(metadata, timestamp, content, file_path):
        """
        Creates a dict of all the data and then writes it into the file
        :param metadata: The meta data
        :param timestamp: the timestamp
        :param content: the content
        :param file_path: The file in which json needs to be written
        :return: None
        """
        output_dict = dict(metadata=metadata, timestamp=timestamp, content=content)
        with open(file_path, 'w') as outfile:
            json.dump(output_dict, outfile, sort_keys=True, indent=4, ensure_ascii=False)
    
    
    def main(input_file_path, output_file_path):
        # get a dict from the loaded json
        data = get_contents_from_json(input_file_path)
    
        # the print() supports multiple args so you don't need multiple print statements
        print('JSON:', json.dumps(data), 'Loaded JSON as dict:', data, sep='\n')
    
        try:
            # load your data from the dict instead of the methods since it's more pythonic
            metadata = data['metadata']
            timestamp = data['timestamp']
            content = data['content']
    
            # just cumulating your print statements
            print("Metadata:", metadata, "Timestamp:", timestamp, "Content:", content, sep='\n')
    
            # write your json to the file.
            write_to_json_file(metadata, timestamp, content, output_file_path)
        except KeyError:
            print('Could not find proper keys to in the provided json')
        except TypeError:
            print('There is something wrong with the loaded data')
    
    
    if __name__ == '__main__':
        main('stack.json', 'stack-out.json')
    

    以上代码的优点:

    1. 更多Modular,因此很容易进行单元测试
    2. 处理exceptions
    3. 可读
    4. 更多pythonic
    5. 评论,因为它们太棒了!

    【讨论】:

    • 很好的答案!谢谢!
    猜你喜欢
    • 2016-10-07
    • 2020-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多