Найти все свойства типа Date в объекте и преобразовать одно и то же свойство из строки в объект Date в клонированном объекте - PullRequest
0 голосов
/ 21 января 2019

У меня сложный объект

{
  "original": {
    "assetName": "2669937-cherry-blossoms-wallpapers.jpg",
    "tags": "",
    "id": 5834
  },
  "uploadState": {
    "status": 3
  },
  "file": {
    "isThumbnailable": false,
    "name": "2669937-cherry-blossoms-wallpapers.jpg",
    "tags": []
  },
  "customFields": [{
    "customFormApplicationId": 2014,
    "customFieldId": 1017,
    "referenceId": 0,
    "referenceType": 0,
    "label": "qaa",
    "orderId": 0,
    "type": 1,
    "value": "",
    "defaultValue": "",
    "properties": "MULTILINE:false|WATERMARK_TEXT:",
    "dateCreated": "0001-01-01T00:00:00",
    "isRequired": true,
    "$$hashKey": "object:22760",
    "requiredValueSet": false
  }, {
    "customFormApplicationId": 2014,
    "customFieldId": 1018,
    "referenceId": 0,
    "referenceType": 0,
    "label": "ddd",
    "orderId": 1,
    "type": 3,
    "properties": "MULTILINE:true|WATERMARK_TEXT:|VISIBLE_LINES:5|DISPLAY_TYPE:1|DATE_FORMAT:1|TIME_FORMAT:1",
    "dateCreated": "0001-01-01T00:00:00",
    "isRequired": true,
    "$$hashKey": "object:22761",
    "isSet": true,
    "value": "",
    "requiredValueSet": false
  }, {
    "customFormApplicationId": 2014,
    "customFieldId": 2017,
    "referenceId": 0,
    "referenceType": 0,
    "label": "drop",
    "orderId": 2,
    "type": 2,
    "value": "",
    "defaultValue": "",
    "properties": "MULTILINE:true|WATERMARK_TEXT:|VISIBLE_LINES:5|ITEMS:v1,v2,v3|DISPLAY_TYPE:1",
    "dateCreated": "0001-01-01T00:00:00",
    "isRequired": false,
    "$$hashKey": "object:22762"
  }],
  "$$hashKey": "object:16951"
}

с динамическими структурами.

Мне нужно глубоко клонировать объект, и я использую этот метод

var clone = $.parseJSON(JSON.stringify(original));

Это единственное, что действительно сработало, поэтому никакой другой метод не может быть использован. Проблема в том, что объекты Date конвертируются в строку Так что вместо

"dateCreated": Mon Jan 21 2019 13:45:06 GMT-0500 (Eastern Standard Time)
__proto__: Object,

У меня есть "dateCreated":"2019-01-21T18:45:06.696Z"

Чтобы преобразовать это обратно в дату, я использую

clone.dateCreated = new Date(original.dateCreated )

ПРОБЛЕМА заключается в том, что мой объект очень сложен и обладает динамическими свойствами, поэтому я не знаю структуру объекта.

Мне нужно написать функцию, которая будет работать на исходном объекте, и проверить каждое свойство, а если это свойство типа Date, перейти к клону к тому же свойству и преобразовать эту строку в Date

Как должна выглядеть функция? Две ключевые проблемы:

1 - запустить все свойства исходного объекта и проверить тип 2 - найти то же свойство в объекте клона

учитывая, что они имеют одинаковую структуру

Я использую ES5 и не пользуюсь библиотекой lodash или подчеркиванием

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Я закончил делать angular.copy объекта, и поскольку объект File не копирует правильно, я просто переопределил его с оригинальным File

var clone = angular.copy(original);
clone.file = original.file
0 голосов
/ 22 января 2019

Если вы настаиваете на использовании JSON.parse (JSON.stringify), то следующее будет рекурсивно обрабатывать полученный объект и преобразовывать любые строковые значения, которые соответствуют регулярному выражению, в Dates.

Он имеет дело только с вероятными типами, полученными в результате обработки JSON, если вам нужно что-то более сложное, вам просто нужно больше - это ... тесты и следующая логика. Надеюсь, комментариев будет достаточно.

// Parse ISO 8601 date YYYY-MM-DDTHH:mm:ssZ
// Z is optional, indicates UTC
// Parses '0001' as 0001 not 1901
function toDate(s) {
  var b = s.split(/\D/);
  var d = new Date(0);
  if (/z$/i.test(s)) {
    d.setUTCFullYear(b[0], b[1]-1, b[2]);
    d.setUTCHours(b[3], b[4], b[5], b[6]||0);
    return d;
  } else {
    d.setFullYear(b[0], b[1]-1, b[2]);
    d.setHours(b[3], b[4], b[5], b[6]||0);
    return d;
  }
}

// Recurse over objects, if any property value is a string that
// matches the ISO 8601 pattern /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?$/
// convert it to a Date object
function stringsToDates(obj) {

  // Simple isObject and isArray functions
  let isObj = value => Object.prototype.toString.call(value) == '[object Object]';
  let isArr = value => Array.isArray(value);
  // Test if value is string date, object or array and convert, recurse or ignore
  let resolveValue = (value, key, obj) => {
    if (typeof value == 'string' && re.test(value)) {
      obj[key] = toDate(value);
    } else if (isArr(value) || isObj(value)) {
      go(value);
    }
  }

  // Regular expression for ISO date string
  var re = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?$/;
  
  // Recursive function looking for strings matching re
  function go(obj) {

    if (isArr(obj)) {
      obj.forEach((value, i, arr) => resolveValue(value, i, arr));
      
    } else if (isObj(obj)) {
      Object.keys(obj).forEach(key => resolveValue(obj[key], key, obj))
    }
  }
  return go(obj);
}

// Test data
var x = {
  aDate: '0001-01-01T00:00:00',  // level 0
  bool: true,
  obj: {arr: ['0002-01-01T00:00:00z', 'string', false]}, // level 2
  arr: ['0003-01-01T00:00:00', null, true, []], // level 1
  obj1: {
    nest: {
      deep: {
        string: 'foo',
        date0: '0004-01-01T00:00:00Z',  // level 4
        date1: '0005-01-01T00:00:00',  // level 4
        arr1: ['0006-01-01T00:00:00z', NaN, {}]  // level 5
      }
    }
  }
}

// Do conversion
stringsToDates(x);
console.log(x);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...