Форматирование данных json для camelCased

Я получаю ответ json от сервера, который выглядит примерно так:

{
    "Response": {
        "FirstName": "John",
        "LastName": "Smith",
        "NickNames": {
            "NameOne": "Johnny",
            "NameTwo": "JohnS",
            "NameThree": "Smithy"
        },
        "Success": true,
        "Errors": []
    }
}

Есть ли способ запустить этот ответ через функцию, чтобы ключ каждой пары значений ключа был бы camelCased?

Таким образом, результат будет выглядеть примерно так:

{
    "Response": {
        "FirstName": "John",
        "LastName": "Smith",
        "NickNames": {
            "NameOne": "Johnny",
            "NameTwo": "JohnS",
            "NameThree": "Smithy"
        },
        "Success": true,
        "Errors": []
    }
}

Если кто-то может указать мне в правильном направлении, это будет здорово.

Спасибо.

Ответ 1

Вы передадите JSON.parse функцию reviver, которая присваивает значения новым свойствам, расположенным ниже.

function reviver(key, val) {
    if (key)
        this[key.charAt(0).toLowerCase() + key.slice(1)] = val;
     else
        return val;
}

var parsed = JSON.parse(myjson, reviver);

Итак, если key имеет по крайней мере один символ, он будет вводить нижний регистр первого символа и добавлять остальное и добавлять этот ключ к объекту и разрешать функции возвращать undefined, чтобы исходный ключ не используется.

Если key не имеет символов, он просто возвращает значение для исходной обработки.

DEMO: http://jsfiddle.net/GrupQ/

Ответ 2

Подход, который предложил пользователь "@I Hate Lazy", с использованием функции "reviver" - правильный. Однако его функция не работала для меня.

Возможно, это потому, что я разбираю массив JSON. Также я использую Resharper, и он жаловался на запах кода:) ('не все пути кода возвращают значение'). Поэтому я использовал функцию из другой проблемы SO, которая сделала для меня:

function camelCaseReviver(key, value) {
    if (value && typeof value === 'object') {
        for (var k in value) {
            if (/^[A-Z]/.test(k) && Object.hasOwnProperty.call(value, k)) {
                value[k.charAt(0).toLowerCase() + k.substring(1)] = value[k];
                delete value[k];
            }
        }
    }
    return value;
}

Ответ 3

Как @Bart говорит, @I Hate Lazy reviver метод не способен анализировать массивы. Вот функциональный рекурсивный (ES6) подход.

function convertKeysToCamelCase(o) {
  if (o === null) {
    return null;
  } else if (o === undefined) {
    return undefined;
  } else if (Array.isArray(o)) {
    return o.map(convertKeysToCamelCase);
  }
  return Object.keys(o).reduce((prev, current) => {
    const newKey = `${current[0].toLowerCase()}${current.slice(1)}`;
    if (typeof o[current] === 'object') {
      prev[newKey] = convertKeysToCamelCase(o[current]);
    } else {
      prev[newKey] = o[current];
    }
    return prev;
  }, {});
}

Ответ 4

@adamjyee Ваше решение работает, за исключением вложенного массива целых чисел. Небольшое исправление может быть:

function convertKeysToCamelCase (o) {
    if (o === null) {
      return null
    } else if (o === undefined) {
      return undefined
    } else if (typeof o === 'number') {
      return o
    } else if (Array.isArray(o)) {
      return o.map(convertKeysToCamelCase)
    }
    return Object.keys(o).reduce((prev, current) => {
      const newKey = `${current[0].toLowerCase()}${current.slice(1)}`
      if (typeof o[current] === 'object') {
        prev[newKey] = convertKeysToCamelCase(o[current])
      } else {
        prev[newKey] = o[current]
      }
      return prev
    }, {})

[Право прокомментировать, но не имеет права голоса: (]

Ответ 5

Вам нужно написать рекурсивную функцию, которая пересекает дерево и возвращает новое дерево, в котором были обновлены ключи в объектах. Рекурсивная функция называла бы себя с любыми подобъектами, с которыми она сталкивается.