在python中加载json的一部分

在python中加载json的一部分,python,Python,我有一个json文件,其中包含大约1000个数据条目。比如说 {"1":"Action","2":"Adventure",....."1000":"Mystery"} 以上只是一个例子 我通过导入json来使用json.load特性。 如何仅从json加载前10个数据项 {"1":"Action","2":"Adventure",....."10":"Thriller"} 我想没有别的办法了。 您必须加载整个内容,然后才能提取所需的密钥 我想没有别的办法了。 必须加载整个内容,然后才能提取所

我有一个json文件,其中包含大约1000个数据条目。比如说

{"1":"Action","2":"Adventure",....."1000":"Mystery"}
以上只是一个例子

我通过导入json来使用json.load特性。 如何仅从json加载前10个数据项

{"1":"Action","2":"Adventure",....."10":"Thriller"}
我想没有别的办法了。 您必须加载整个内容,然后才能提取所需的密钥

我想没有别的办法了。
必须加载整个内容,然后才能提取所需的键。

JSON对象,如Python字典,没有顺序。您也无法控制加载了多少对象,无论如何都不能使用标准库
json
模块

加载后,您可以获取具有最低键值的十个键值对:

import heapq
import json

data = json.loads(json_string)
limited = {k: data[k] for k in heapq.nsmallest(data, 10, key=int)}
无论
数据的大小如何,都将有效地挑选出10个最小的键

当然,如果按键总是连续的,并且总是从
1
开始,您也可以在此处使用
范围()

data = json.loads(json_string)
limited = {str(k): data[str(k)] for k in range(1, 11)}
如果要按文件定义顺序捕获对象,可以使用
object\u pairs\u hook
参数来
json.load()
json.load()

后一种方法的演示:

>>> import json
>>> class FirstTenDict(dict):
...     def __init__(self, pairs):
...         super(FirstTenDict, self).__init__(pairs[:10])
... 
>>> json_data = '''\
... {"foo42": "bar", "foo31": "baz", "foo10": "spam", "foo44": "ham", "foo1": "eggs",
...  "foo24": "vikings", "foo21": "monty", "foo88": "python", "foo11": "eric", "foo65": "idle",
...  "foo13": "will", "foo31": "be", "foo76": "ignored"}
... '''
>>> json.loads(json_data)
{'foo1': 'eggs', 'foo88': 'python', 'foo44': 'ham', 'foo10': 'spam', 'foo76': 'ignored', 'foo42': 'bar', 'foo24': 'vikings', 'foo11': 'eric', 'foo31': 'be', 'foo13': 'will', 'foo21': 'monty', 'foo65': 'idle'}
>>> json.loads(json_data, object_pairs_hook=FirstTenDict)
{'foo1': 'eggs', 'foo88': 'python', 'foo44': 'ham', 'foo10': 'spam', 'foo24': 'vikings', 'foo11': 'eric', 'foo21': 'monty', 'foo42': 'bar', 'foo31': 'baz', 'foo65': 'idle'}
>>> import pprint
>>> pprint.pprint(_)
{'foo1': 'eggs',
 'foo10': 'spam',
 'foo11': 'eric',
 'foo21': 'monty',
 'foo24': 'vikings',
 'foo31': 'baz',
 'foo42': 'bar',
 'foo44': 'ham',
 'foo65': 'idle',
 'foo88': 'python'}

JSON对象,如Python字典,没有顺序。您也无法控制加载了多少对象,无论如何都不能使用标准库
json
模块

加载后,您可以获取具有最低键值的十个键值对:

import heapq
import json

data = json.loads(json_string)
limited = {k: data[k] for k in heapq.nsmallest(data, 10, key=int)}
无论
数据的大小如何,都将有效地挑选出10个最小的键

当然,如果按键总是连续的,并且总是从
1
开始,您也可以在此处使用
范围()

data = json.loads(json_string)
limited = {str(k): data[str(k)] for k in range(1, 11)}
如果要按文件定义顺序捕获对象,可以使用
object\u pairs\u hook
参数来
json.load()
json.load()

后一种方法的演示:

>>> import json
>>> class FirstTenDict(dict):
...     def __init__(self, pairs):
...         super(FirstTenDict, self).__init__(pairs[:10])
... 
>>> json_data = '''\
... {"foo42": "bar", "foo31": "baz", "foo10": "spam", "foo44": "ham", "foo1": "eggs",
...  "foo24": "vikings", "foo21": "monty", "foo88": "python", "foo11": "eric", "foo65": "idle",
...  "foo13": "will", "foo31": "be", "foo76": "ignored"}
... '''
>>> json.loads(json_data)
{'foo1': 'eggs', 'foo88': 'python', 'foo44': 'ham', 'foo10': 'spam', 'foo76': 'ignored', 'foo42': 'bar', 'foo24': 'vikings', 'foo11': 'eric', 'foo31': 'be', 'foo13': 'will', 'foo21': 'monty', 'foo65': 'idle'}
>>> json.loads(json_data, object_pairs_hook=FirstTenDict)
{'foo1': 'eggs', 'foo88': 'python', 'foo44': 'ham', 'foo10': 'spam', 'foo24': 'vikings', 'foo11': 'eric', 'foo21': 'monty', 'foo42': 'bar', 'foo31': 'baz', 'foo65': 'idle'}
>>> import pprint
>>> pprint.pprint(_)
{'foo1': 'eggs',
 'foo10': 'spam',
 'foo11': 'eric',
 'foo21': 'monty',
 'foo24': 'vikings',
 'foo31': 'baz',
 'foo42': 'bar',
 'foo44': 'ham',
 'foo65': 'idle',
 'foo88': 'python'}
简言之,你不能

虽然每个条目都是一个JSON条目,但该文件作为一个整体是一个有效的JSON文件

例如:

import ijson

def iter_items(parser):
    for prefix, event, value in parser:
        if event == 'string':
            yield prefix, value

with open('filename.json') as infile:
    items = iter_items(ijson.parser(infile))
    # choose one of the following
    # first 10 items from the file regardless of keys
    print dict(itertools.islice(items, 10))
    # least 10 keys when considered as integers
    print dict(heapq.nsmallest(items, 10, lambda p: int(p[0])))
“1”:“Action”
是正确的JSON格式,但不能单独加载

为了能够将其作为JSON格式导入,您需要它的完整语法
{“1”:“Action”}

您需要做的是仍然加载整个文件,然后将前10行分配给一个变量。

简而言之,您不能

虽然每个条目都是一个JSON条目,但该文件作为一个整体是一个有效的JSON文件

例如:

import ijson

def iter_items(parser):
    for prefix, event, value in parser:
        if event == 'string':
            yield prefix, value

with open('filename.json') as infile:
    items = iter_items(ijson.parser(infile))
    # choose one of the following
    # first 10 items from the file regardless of keys
    print dict(itertools.islice(items, 10))
    # least 10 keys when considered as integers
    print dict(heapq.nsmallest(items, 10, lambda p: int(p[0])))
“1”:“Action”
是正确的JSON格式,但不能单独加载

为了能够将其作为JSON格式导入,您需要它的完整语法
{“1”:“Action”}


您需要做的是仍然加载整个文件,然后将前10行分配给一个变量。

您可以使用迭代解析json(也就是说,不是“一次全部解析”),并且假设您的输入真的像您的示例一样简单:

import ijson

def iter_items(parser):
    for prefix, event, value in parser:
        if event == 'string':
            yield prefix, value

with open('filename.json') as infile:
    items = iter_items(ijson.parser(infile))
    # choose one of the following
    # first 10 items from the file regardless of keys
    print dict(itertools.islice(items, 10))
    # least 10 keys when considered as integers
    print dict(heapq.nsmallest(items, 10, lambda p: int(p[0])))
显然,第二种方法仍然需要读取整个文件,它不需要立即将整个文件保存在内存中。避免这种情况是对1000个小键值对的过早优化,但不管怎样。我发现这个问题非常有趣,可以使用一个我以前从未考虑过的库,因为有时候json文件非常大,而且与SAX解析器(基于事件的XML流式解析器)非常相似


顺便说一下,如果顺序很重要,那么这个JSON的生产者可能应该在JSON中放入一个数组。但作为消费者,您可能对此无能为力。

您可以使用迭代解析json(也就是说,不是“一次全部解析”),并且假设您的输入真的像您的示例一样简单:

import ijson

def iter_items(parser):
    for prefix, event, value in parser:
        if event == 'string':
            yield prefix, value

with open('filename.json') as infile:
    items = iter_items(ijson.parser(infile))
    # choose one of the following
    # first 10 items from the file regardless of keys
    print dict(itertools.islice(items, 10))
    # least 10 keys when considered as integers
    print dict(heapq.nsmallest(items, 10, lambda p: int(p[0])))
显然,第二种方法仍然需要读取整个文件,它不需要立即将整个文件保存在内存中。避免这种情况是对1000个小键值对的过早优化,但不管怎样。我发现这个问题非常有趣,可以使用一个我以前从未考虑过的库,因为有时候json文件非常大,而且与SAX解析器(基于事件的XML流式解析器)非常相似

顺便说一下,如果顺序很重要,那么这个JSON的生产者可能应该在JSON中放入一个数组。但作为消费者,你可能对此无能为力。

你有两个选择:

如果使用Python>=3.1,则可以使用

from collections import OrderedDict
decoder = json.JSONDecoder(object_pairs_hook=OrderedDict)
data = decoder.decode(datastring)
这将解码整个文件,但保持所有键值对的顺序与文件中的顺序相同

然后,您可以使用以下内容对前n个项目进行切片

result = OrderedDict((k,v) for (k,v),i in zip(data.items(), range(n)))
这不是很有效,但您将获得前10个条目,因为它们是用JSON编写的

第二种选择,也是效率更高但难度更大的选择,是使用@steve jessop提到的迭代JSON解析器,如
ijson

如果且仅当您的JSON文件始终是平面的(不包含任何子对象或列表),如您在问题中的示例,以下代码将把前10个元素放入结果中。更复杂的文件需要更复杂的解析器代码

import ijson
result = {}
for prefix, event, value in ijson.parse(file):
  if event == 'map_key':
    if len(result) > 10:
      break
  if prefix:
    result[prefix] = value
您有两个选择:

如果使用Python>=3.1,则可以使用

from collections import OrderedDict
decoder = json.JSONDecoder(object_pairs_hook=OrderedDict)
data = decoder.decode(datastring)
这将解码整个文件,但保持所有键值对的顺序与文件中的顺序相同

然后,您可以使用以下内容对前n个项目进行切片

result = OrderedDict((k,v) for (k,v),i in zip(data.items(), range(n)))
这不是很有效,但您将获得前10个条目,因为它们是用JSON编写的

第二种选择,也是效率更高但难度更大的选择,是使用@steve jessop提到的迭代JSON解析器,如
ijson

如果且仅当您的JSON文件始终是平面的(不包含任何子对象或列表),如您在问题中的示例,以下代码将把前10个元素放入结果中。更复杂的文件需要更复杂的解析器代码

import ijson
result = {}
for prefix, event, value in ijson.parse(file):
  if event == 'map_key':
    if len(result) > 10:
      break
  if prefix:
    result[prefix] = value
JSON是一个对象repr