(Python)将新的和现有的JSON与重复数据删除相结合

时间:2015-12-18 09:59:01

标签: python json merge

我正在使用Python查询API,此API发送最后X个事件的JSON,我想保留它发送给我的历史记录。

这就是API发送的内容,我的平面历史文件中有相同类型的元素(但是有更多相同的对象)。 API和我的最终文件没有用于设置字典的密钥。

[{
    "Item1": "01234",
    "Item2": "Company",
    "Item3": "XXXXXXXXX",
    "Item4": "",
    "Item5": "2015-12-17T12:00:01.553",
    "Item6": "2015-12-18T12:00:00"
},
{
    "Item1": "01234",
    "Item2": "Company2",
    "Item3": "XXXXXXX",
    "Item4": null,
    "Item5": "2015-12-17T16:49:23.76",
    "Item6": "2015-12-18T11:00:00",
}]

如果API的元素不在原始文件中,我该如何添加? 我有一个打开/关闭文件的框架,但对处理没有太多想法。

main_file=open("History.json","r")
new_items=[]
api_data=requests.get(#here lies the api address and the header)
#here should be the deplucation/processing process
for item in api_data
    if item not in main_file 
        new_items.append(item)
main_file.close()
try:
    file_updated = open("History.json",'w')
    file_updated.write(new_items + main_file)
    file_updated.close()
    print("File updated")
except :
    print("Error writing file")

编辑:我使用json对象方法来执行此操作:

from collections import namedtuple
Event = namedtuple('Event', 'Item1, Item2, Item3, Item4, Item5, Item6')
def parse_json_events(text):
    events = [ Event(**k) for k in json.loads(text) ]
    return events
if path.exists('Mainfile.json'):
    with open('Mainfile.json') as data_file:
        local_data = json.load(data_file)
        print(local_data.text) #debug purposes
        events_local=parse_json_events(local_data.text)
else:
    events_local=[]
events_api=parse_json_events(api_request.text)
inserted_events=0 
for e in events_api[::-1]:
    if e not in events_local:
        events_local.insert(0, e)
        inserted_events=inserted_events+1
print("inserted elements %d"  % inserted_events)
print(events_local) # this is OK, gives me a list of events
print(json.dump(events_local)) # this ... well... I want the list of object to be serialized but I get this error : 
  

TypeError:dump()缺少1个必需的位置参数:'fp'

2 个答案:

答案 0 :(得分:1)

我认为解决这个问题的最佳方法是考虑您的数据结构。看起来你现在正在使用与api相同的数据结构。

这些项目字段中是否有Id?如果是,请使用该字段进行重复数据删除。但是对于这个例子,我将使用公司名称。

with open('history.json') as f:
    historic_data = json.load(f)
    api_data = requests.get()
    for item in api_data:
        historic_data[item['Item2']] = item
    f.write(json.dumps(historic_data))

每次本例中的名称已经存在于字典中时,它将被覆盖。如果该名称不存在,则会添加该名称。

答案 1 :(得分:1)

通常,您可以通过使用/不使用第三方工具(如Avro,Thrift等)定义架构来解决此类问题。基本上,您从API获得的每条记录都需要使用您正在使用的编程语言转换为实体。

我们以此JSON对象为例:

{
    "Item1": "01234",
    "Item2": "Company",
    "Item3": "XXXXXXXXX",
    "Item4": "",
    "Item5": "2015-12-17T12:00:01.553",
    "Item6": "2015-12-18T12:00:00"
},

如果您有类似

的架构
Company(object):
  company_number = ...
  name = ...
  # other fields

然后,您需要做的就是序列化和反序列化原始数据。

理想情况下,您从API中读取JSON响应,然后您可以简单地将每个json对象拆分为架构对象(使用或不使用工具)。在伪代码中:

api_client = client(http://..., )
response = api_client.get("/resources")
json = response.json 
companies = parse_json_companies(json) # list of Company objects

此时,处理从api获取的数据非常容易。您应该对存储在文件系统中的文件执行相同的操作。加载文件并反序列化记录(到公司对象)。然后,比较对象将很容易,因为它们将像“普通”Python对象,因此您可以执行比较等。

例如:

from collections import namedtuple
import json
Company = namedtuple('Company', 'Item1, Item2, Item3, Item4, Item5, Item6')
def parse_json_companies(text):
  companies = [Company(**k) for k in json.loads(text)]
  return companies

>>> companies = parse_json_companies(response.json)
>>> companies
[Company(Item1='01234', Item2='Company', Item3='XXXXXXXXX', Item4=u'', Item5='2015-12-17T12:00:01.553', Item6='2015-12-18T12:00:00'), Company(Item1='01234', Item2='Company2', Item3='XXXXXXX', Item4=None, Item5='2015-12-17T16:49:23.76', Item6='2015-12-18T11:00:00')]

.dump(obj,fp)错误后更新。

如果您使用json.dump收到错误,请参阅documentation。它明确指出 obj fp 是必需的参数。

  

使用此转换表将obj作为JSON格式的流序列化为fp(.write() - 支持类似文件的对象)。

因此,您需要传递支持.write的对象(例如,以写入模式打开的文件)。