PERL中的JSON解码 - 维护原始数据类型

时间:2015-04-22 17:06:13

标签: json perl mongodb

我正在编写一个简单的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_imagepublish_datedata_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很新。对不起,如果这是一个微不足道的问题。

3 个答案:

答案 0 :(得分:3)

  

我正在为文档提供自定义_id,我希望将其转换为NumberLong类型。从上面的JSON可以看出,这正如预期的那样工作。但请注意show_image,publish_date和data_version的其他非字符串值如何转换为它的对象表示。

在您的示例中,除了show_image的布尔值(当前正在转换为二进制数据)之外,所有数据类型实际上都是匹配的。

NumberLong shell查询时,预计数字类型会显示为NumberIntmongomongo 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。