尝试将insert_one放入集合后,收到以下错误:
bson.errors.InvalidDocument: cannot encode object: Decimal('0.16020'), of type: <class 'decimal.Decimal'>
当JSON不包含decimal.Decimal
对象时,代码运行良好。如果有解决方案,您可以考虑以递归的方式进行编码,以使整个python字典json_dic
兼容插入MongoDB(因为json.dic
条目中有不止一个decimal.Decimal类的示例)。
**编辑1:**下面是我正在处理的JSON
import simplejson as json
from pymongo import MongoClient
json_string = '{"A" : {"B" : [{"C" : {"Horz" : 0.181665435,"Vert" : 0.178799435}}]}}'
json_dict = json.loads(json_string)
this_collection.insert_one(json_dict)
这将生成bson.errors.InvalidDocument: cannot encode object: Decimal('0.181665435'), of type: <class 'decimal.Decimal'>
**EDIT 2:**不幸的是,我上面的示例过于简化了我现有的JSON,而@Belly Buster提供的答案(尽管上面的JSON运行良好)显示了一个错误:
AttributeError: 'decimal.Decimal' object has no attribute 'items'
使用我的实际JSON,所以我在这里提供完整的JSON,希望能找出问题所在(也是as a screen-shot):
json_string =
'
{
"Setting" : {
"GridOptions" : {
"Student" : "HighSchool",
"Lesson" : 1,
"Attended" : true
},
"Grades" : [
80,
50.75
],
"Count" : 2,
"Check" : "Coursework",
"Passed" : true
},
"Slides" : [
{
"Type" : "ABC",
"Duration" : 1.5
},
{
"Type" : "DEF",
"Duration" : 0.5
}
],
"Work" : {
"Class" : [
{
"Time" : 123456789,
"Marks" : {
"A" : 50,
"B" : 100
}
}
],
"CourseWorkDetail" : [
{
"Test" : {
"Mark" : 0.987654321
},
"ReadingDate" : "Feb162006",
"Reading" : 300.001,
"Values" : [
[
0.98765
],
[
-0.98765
]
]
},
{
"Test" : {
"Mark" : 0.123456789
},
"ReadingDate" : "Jan052010",
"Reading" : 200.005,
"Values" : [
[
0.12345
],
[
-0.12345
]
]
}
]
},
"listing" : 5
}
'
**编辑3:**对下面答案的补充,您可以在字典中递归迭代,并使用答案中的函数
def iterdict(dict_items, debug_out):
for k, v in dict_items.items():
if isinstance(v):
iterdict(v)
else:
dict_items[k] = convert_decimal(v)
return dict_items
5条答案
按热度按时间f3temu5u1#
编辑:
convert_decimal()
函数将在复杂的dict结构中执行Decimal到Decimal128的转换:给出:
原件:
要将一个十进制转换为MongoDB满意的Decimal128,先将其转换为字符串,然后再转换为Decimal128。
给出:
axzmvihb2#
Pymongo不能识别
Decimal
-这就是为什么你会得到错误。正确的pymongo插入是
coll.insert_one({"number1": Decimal128('8.916')})
。您还需要导入-
from bson import Decimal128
现在,如果希望在不将
Decimal
更改为Decimal 128 '的情况下处理JSON文件,可以修改import语句。nwlls2ji3#
注:
从PyMongo的decimal128文档中:
为确保计算结果始终存储为BSON Decimal128,请使用
create_decimal128_context()
返回的上下文(注:如上面的示例代码所示)。sauutmhj4#
我建议只添加一个编解码器来在插入时自动转换数据类型。如果你递归地改变数据类型来使用Decimal128对象,你可能会破坏与现有代码的兼容性。
您可以按照教程创建一个简单的decimal.Decimal编解码器,请参阅pymongo docs here
js81xvg65#
已接受的答案here部分正确,但未通过我们使用
pytest
编写的测试,示例数据如下:这里嵌套数组是这样的。我稍微改进了一下,现在的一个通过了测试:
当你把它打印出来的时候