我正在编写一个简单的perl脚本来从文件中读取JSON并插入到MongoDB中。但我面临着json解码的问题。
原始json中的所有非字符串值都将在decode_json
之后转换为对象类型。
输入JSON(只是它的一部分,因为它的原始版本很大) -
{
"_id": 2006010100000801089,
"show_image" : false,
"event" : "publish",
"publish_date" :1136091600,
"data_version" : 1
}
插入MongoDB的JSON -
{
"_id": NumberLong("2006010100000801089"),
"show_image" : BinData(0,"MA=="),
"event" : "publish",
"publish_date" :NumberLong(1136091600),
"data_version" : NumberLong(1)
}
我正在为文档提供自定义_id
,我希望将其转换为NumberLong
类型。从上面的JSON可以看出,这正如预期的那样工作。但请注意show_image
,publish_date
和data_version
的其他非字符串值如何转换为其对象表示。
有什么方法可以保留这些值的原始类型吗?
执行插入的Perl代码片段 -
use MongoDB;
use MongoDB::OID;
use JSON;
use JSON::XS
while(my $record = <$source_file>) {
my $record_decoded = decode_json($record);
$db_collection->insert($record_decoded);
}
Perl版本使用v5.18.2。
我抬头JSON::XS docs但找不到办法做到这一点。任何帮助表示赞赏。提前谢谢!
我对perl很新。对不起,如果这是一个微不足道的问题。
答案 0 :(得分:3)
我正在为文档提供自定义_id,我希望将其转换为NumberLong类型。从上面的JSON可以看出,这正如预期的那样工作。但请注意show_image,publish_date和data_version的其他非字符串值如何转换为它的对象表示。
在您的示例中,除了show_image
的布尔值(当前正在转换为二进制数据)之外,所有数据类型实际上都是匹配的。
从NumberLong
shell查询时,预计数字类型会显示为NumberInt
或mongo
。 mongo
shell使用JavaScript,它只有single numeric type Number
(64位浮点)。像NumberLong()
和NumberInt()
这样的Shell帮助程序用于表示MongoDB的BSON data types中没有本机JavaScript等效值的值。
参考我的示例JSON,我希望将show_image的值插入为false而不是BinData(0,“MA ==”),并将publish_date插入为1136091600而不是NumberLong(1136091600)
如果适合您的用例,可以将publish_date
作为Unixtime插入,但您可能会发现使用MongoDB的Date
type更有用。有查询日期的便捷方法,包括Date Aggregation Operators。仅供参考,日期字段将显示在mongo
shell中,并带有ISODate()
包装。
show_image
的布尔值肯定需要帮助。
如果您使用Data::Dumper
检查decode_json()
的结果,您会看到show_image
字段是受祝福的对象:
'show_image' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' )
为了在MongoDB中获得预期的boolean
值,MongoDB模块文档中推荐的方法是使用boolean
模块(参见:MongoDB::DataTypes)。
我找不到JSON或JSON :: XS的明显内置选项来支持将布尔值序列化为JSON模拟布尔类以外的其他内容,但一种解决方案是使用Data::Clean::Base
模块是Data::Clean::JSON
发行版的一部分。
示例代码段(不包括MongoDB设置):
use Data::Clean::Base;
use boolean;
my $cleanser = Data::Clean::Base->new(
'JSON::XS::Boolean' => ['call_func', 'boolean::boolean'],
'JSON::PP::Boolean' => ['call_func', 'boolean::boolean']
);
while (my $record = <$source_file>) {
my $record_decoded = decode_json($record);
$cleanser->clean_in_place($record_decoded);
$db_collection->insert($record_decoded);
}
MongoDB 3.0.2中保存的示例记录:
{
"_id": NumberLong("2006010100000801089"),
"event": "publish",
"data_version": NumberLong("1"),
"show_image": false,
"publish_date": NumberLong("1136091600")
}
答案 1 :(得分:0)
JSON数据仅包含(双精度)数字,字符串和特殊值 true , false 和 null 。它们可以排列成数组或“对象”(哈希)。
MongoDB
引擎正在将这些基本类型转换为更复杂的内容,但原始值在$record_decoded
引用的哈希中可用,如此
$record_decoded->{_id}
$record_decoded->{show_image}
$record_decoded->{event}
$record_decoded->{publish_date}
$record_decoded->{data_version}
这就是你想要的吗?
答案 2 :(得分:0)
JSON :: XS中的object serialization文档(特别是allow_tags
)可能会执行您想要的操作。但请注意,这不是标准的JSON功能,只适用于JSON :: XS。