以编程方式替换 JSON 对象

Posted

技术标签:

【中文标题】以编程方式替换 JSON 对象【英文标题】:Replace JSON Object Programmatically 【发布时间】:2015-08-03 17:50:56 【问题描述】:

我正在寻找替换文件中 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"

每个文件中有 NUMEROUS(100 个)对象,字段的值不同。我需要检查并用新格式替换每个 createdAtupdatedAt 对象。日期无关紧要。我可以让它们成为任何东西。

我可以手动完成,但实际上我需要一两天的时间来完成全职工作(我知道,我试着做一个文件,但 1/2 小时后我放弃了,它正在逐渐消失太长)。

如何以编程方式执行此操作?

正则表达式?赛德?还有什么?

最后一点:我只需要这样做一次。在那之后,我不需要再这样做了。

感谢您的任何提示!

示例 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/'))
);

【问题讨论】:

如果是我,我会编写一个节点脚本将其读取为 JSON,然后将其写回为 JSON。基本上将日期对象转换为字符串,然后将其保存回来。我不想为你编写代码,但它至少是一个起点。 我不会去手动解析文本文件——你熟悉哪些编程语言/环境?您可以使用几乎任何可以读写 JSON 的语言来执行此操作 - 它将读取和反序列化现有的 JSON,根据需要转换适用的字段,然后序列化和重写文件。 @JoeEnos 伟大的思想家认为喜欢 ;) 我会编写一个 Node.js 脚本,它使用流进行文件 i/o。使用fs 流来读取数据和写入结果,中间使用您自己的简单转换流。 现在我想起来你甚至可以使用 gulpjs 来做到这一点。 (现在我对它感兴趣) 【参考方案1】:

为什么不手动呢?

   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 树。不难,只是想知道我是否错误地接近它。 在最终时间戳上输出“Z”时请注意无时区日期构造... 我现在将采用我们拥有的已知值并将其放入这些字段中。不过感谢您的提醒!【参考方案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/'))
);

【讨论】:

我已经安装了 gulp 和 node/etc。这看起来与我正在做的相似,只是更优雅! :) 谢谢!我会用这个作为我的新起点。我很高兴我当时走在正确的道路上。谢谢@nix 如果您有任何问题,请告诉我。 以你上面的方法为灵感,写出了我需要的东西。感谢您的提示。【参考方案3】:

打开每个文件,使用转换函数更改属性,然后保存新的 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

【讨论】:

以上是关于以编程方式替换 JSON 对象的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式快速编写 JSON 文件

以编程方式替换片段

以编程方式替换选择器图像

Ace:以编程方式打开搜索/替换框

如何以编程方式从动态 JObject 获取属性

在目标 c 中以编程方式替换菜单视图