以编程方式替换JSON对象

5
我将翻译以下关于IT技术的内容:

我正在寻找一种最有效的方法来替换文件中的JSON对象。

20150628 - 此帖子底部更新

以下是情况:

我有许多JSON文件,这些文件中有大量的JSON代码(有时达到20-30K行),这些都是我们各种测试程序的配置。最近需要更改一个对象,从原来的这个:

"createdAt": {
    "year": 2014,
    "month": 11,
    "dayOfMonth": 24,
    "hourOfDay": 2,
    "minute": 22,
    "second": 54
}

将其转化为以下格式:
"createdAt":"2015-05-12T21:14:51Z"

让我们更简单一些。 我想要替换我的JSON对象中所有的createdAtupdatedAt字段(可能有很多个)为:

   "createdAt":"2015-05-12T21:14:51Z"

或者
   "updatedAt":"2015-05-12T21:14:51Z"

每个文件中都有成百上千(数百个)的对象,这些对象的字段值不同。我需要遍历并用新格式替换每个createdAtupdatedAt对象。日期并不重要,可以是任何值。
我可以手动完成此操作,但需要全职工作一两天才能完成(我知道,我尝试过处理一个文件,但半小时后我放弃了,花费的时间太长了)。
如何通过编程实现呢?正则表达式?Sed?还是其他什么?
最后说明:我只需要做一次。之后,我就不需要再做了。
感谢任何提示!
示例JSON:(想象一下真实的JSON有30,000行!):)
{ "products": [
          {
            "displayOrder": 3,
            "product": {
              "foo": "bar",
              "createdAt": {
                "year": 2014,
                "month": 11,
                "dayOfMonth": 24,
                "hourOfDay": 2,
                "minute": 22,
                "second": 54
              },
              "description": "Fizz Bin",
              "id": "8765309",
              "modelNumber": "call-it",
              "name": "Boom",
              "price": {
                "amount": 100,
                "currency": "USD"
              },
              "type": "Active",
              "updatedAt": {
                "year": 2015,
                "month": 1,
                "dayOfMonth": 27,
                "hourOfDay": 19,
                "minute": 33,
                "second": 25
              }
            }
          },
          {
            "displayOrder": 4,
            "product": {
              "foo": "barx",
              "createdAt": {
                "year": 2013,
                "month": 1,
                "dayOfMonth": 4,
                "hourOfDay": 3,
                "minute": 2,
                "second": 5
              },
              "description": "Fizzy Stuff",
              "id": "876511111",
              "modelNumber": "zoom-zoom-1000",
              "name": "Zoom Zoom 1000",
              "price": {
                "amount": 1000,
                "currency": "USD"
              },
              "type": "Active",
              "updatedAt": {
                "year": 2011,
                "month": 5,
                "dayOfMonth": 25,
                "hourOfDay": 15,
                "minute": 35,
                "second": 55
              }
            }
          }
        ]
}

更新 20150628

对于那些想知道的人,这是我编写的gulpfile,以实现我想要的精确内容。它基于已接受的答案。当找到我要查找并替换的内容时,它将递归地搜索树。虽然它不是世界上最漂亮的东西,但它确实做到了我所需要的,并为我节省了几个星期的手动时间。处理所有文件的总时间?少于100毫秒。太神奇了。

var gulp = require('gulp');
var change = require('gulp-change');

function searchTreeForDates(obj) {
    if(typeof(obj) === 'object') {
        for (var key in obj) {
            if (typeof(obj[key]) === 'object' && (key === 'createdAt' || key === 'updatedAt')) {
                obj[key] = "2015-06-29T00:53:00Z";
            } else {
                obj[key] = searchTreeForDates(obj[key])
            }
        }
    }
    return obj; 
}

function updateDate(content) {
    var obj = JSON.parse(content);
    obj = searchTreeForDates(obj);
    return JSON.stringify(obj);
}

gulp.task('change', function() {
    return gulp.src('*.json')
        .pipe(change(updateDate))
        .pipe(gulp.dest('changed/'))
});

如果是我,我会编写一个Node脚本将其读取为JSON,然后再将其写回JSON。基本上将日期对象转换为字符串,然后保存回去。我不想为你编写代码,但至少这是一个起点。 - Nix
我不会选择手动解析文本文件-你熟悉哪些编程语言/环境?你几乎可以使用任何能读取和写入JSON的语言来完成此任务-它将读取和反序列化现有的JSON,根据您的需要转换适用的字段,然后序列化和重写文件。 - Joe Enos
1
@JoeEnos 伟大的思想总是相似的 ;) - Nix
我会编写一个使用流进行文件输入/输出的Node.js脚本。使用fs流来读取数据和写入结果,并在中间使用自己的简单转换流。 - joews
现在我想起来,你甚至可以使用gulpjs来完成它。(现在我对此很感兴趣) - Nix
显示剩余2条评论
3个回答

2

以下是初步的尝试。您需要实现自己的“日期解析逻辑”。这需要您安装gulp并将其保存在gulpfile.js中。您可能需要循环遍历所有“日期”对象属性,但这个逻辑并不难。

var gulp = require('gulp');
var change = require('change');

function translateDate(dateField){
    return dateField.A + dateField.b + ...;

}
function updateDate(content) {
    var obj = JSON.parse(content);
    //loop over the obj properties and call the below
    // for the ones you want to change.
    obj.dateField = translateDate(obj.dateField);
    return JSON.stringify(obj);
}

gulp.task('change', function() {
    return gulp.src('**/*.json')
      .pipe(change(updateDate))
      .pipe(gulp.dest('changed/'))
});

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Donn Felker
如果您有任何问题,请告诉我。 - Nix
使用了您上面的方法作为灵感,并编写了我所需要的内容。感谢您的建议。 - Donn Felker

0
为什么不手动呢?
   function formatDate(dateObject){
       var formattedDate = 
                  dateObject['year']+'-'+
                  dateObject['month']+'-'+ 
                  dateObject['dayOfMonth']+'T'+
                  dateObject['hourOfDay']+':'+
                  dateObject['minute']+':'+
                  dateObject['second']+'Z';
    }
    var jsonArray = {...};

    for(var key in jsonArray){
        for(var i = 0; i < jsonArray[key].length; i++){
            jsonArray[key][i]['createdAt'] = formatDate(jsonArray[key]['createdAt']); 
            jsonArray[key][i]['updatedAt'] = formatDate(jsonArray[key]['updatedAt']); 

    }
}

问题是,这些createdAt和updatedAt在JSON文件中随处可见。上面的示例非常简化。我基本上需要遍历整个JSON树。不难,只是想知道我是否错误地处理了它。 - Donn Felker
在输出最终时间戳上的“Z”时,请注意无时区日期构造。 - dandavis
我现在只是将我们已经知道的值放入这些字段中。不过还是谢谢你提醒我! - Donn Felker

0
打开每个文件,使用转换函数更改属性,然后保存新的JSON:
function changeDate(obj) {
  var newObject = obj.year + '-' + obj.month + '-' + obj.dayOfMonth + 'T' + obj.hourOfDay + ':' + obj.minute + ':' + obj.second;
  return newObject;
}

// here you open the file and stores it's content in the products variable.
for (var i = 0; i < products.length; i++) {
  var product = products[i];
  product.product.createdAt = changeDate(product.product.createdAt);
  product.product.updatedAt = changeDate(product.product.updatedAt);
}
// .. now you need to save the modified json

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接