无法将dict对象写为正确的JSON文件

时间:2018-04-06 16:26:09

标签: json python-3.x

我尝试从文件中读取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。 下面我附上一个获取值的python程序,创建新的JSON并将其写入文件。

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)

但问题是创建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。我错了什么?

2 个答案:

答案 0 :(得分:2)

解决方案:

更改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 - 它是JSON表示在create_json(...)函数中创建的字典。但在write_json_to_file(file_name, json_content)内,您正在致电:

json.dump(json_content, file)

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

答案 1 :(得分:1)

问题

  

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

如何解决?

  

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

其他建议

看到您的代码后,我发现您来自java背景,而在java getThis()getThat()是模拟代码的好方法因为我们在classes中的java代表我们的代码,所以python只会导致代码的readability出现问题PEP 8 {{3 }}。

我已更新以下代码:

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. 评论因为它们真棒!