web-dev-qa-db-ja.com

返されたJSONオブジェクトプロパティを(下から順に)camelCaseに変換します

次のようなAPIからJSONが返されました。

Contacts: [{ GivenName: "Matt", FamilyName:"Berry" }]

これを私のコードスタイル(camelCase-小文字の最初の文字)と一貫性を保つために、配列を変換して以下を生成したいと思います。

 contacts: [{ givenName: "Matt", familyName:"Berry" }]

これを行う最も簡単/最良の方法は何ですか?新しいContactオブジェクトを作成し、返された配列内のすべての連絡先を反復処理しますか?

var jsonContacts = json["Contacts"],
    contacts= [];

_.each(jsonContacts , function(item){
    var contact = new Contact( item.GivenName, item.FamilyName );
    contacts.Push(contact);
});

または、元の地図を作成したり、何らかの形で変換したりできますか?

49
Jon Wells

JavaScriptオブジェクトのすべてのプロパティを正しくキャメルケースする信頼性の高い再帰関数を次に示します。

function toCamel(o) {
  var newO, origKey, newKey, value
  if (o instanceof Array) {
    return o.map(function(value) {
        if (typeof value === "object") {
          value = toCamel(value)
        }
        return value
    })
  } else {
    newO = {}
    for (origKey in o) {
      if (o.hasOwnProperty(origKey)) {
        newKey = (origKey.charAt(0).toLowerCase() + origKey.slice(1) || origKey).toString()
        value = o[origKey]
        if (value instanceof Array || (value !== null && value.constructor === Object)) {
          value = toCamel(value)
        }
        newO[newKey] = value
      }
    }
  }
  return newO
}

テスト:

var obj = {
  'FirstName': 'John',
  'LastName': 'Smith',
  'BirthDate': new Date(),
  'ArrayTest': ['one', 'TWO', 3],
  'ThisKey': {
    'This-Sub-Key': 42
  }
}

console.log(JSON.stringify(toCamel(obj)))

出力:

{
    "firstName":"John",
    "lastName":"Smith",
    "birthDate":"2017-02-13T19:02:09.708Z",
    "arrayTest": [
        "one", 
        "TWO", 
        3
    ],
    "thisKey":{
        "this-Sub-Key":42
    }
}
60
brandonscript

アンダースコアの代わりに lodash を使用すると、次のようになります。

_.mapKeys(obj, (v, k) => _.camelCase(k))

これにより、TitleCasesnake_caseの両方がcamelCaseに変換されます。ただし、再帰的ではないことに注意してください。

57
mik01aj

プレーンオブジェクトのキーをsnake_caseからcamelCaseに変更するにはrecursively以下を試してください
Lodash を使用):

function objectKeysToCamelCase(snake_case_object) {
  var camelCaseObject = {};
  _.forEach(
    snake_case_object,
    function(value, key) {
      if (_.isPlainObject(value) || _.isArray(value)) {     // checks that a value is a plain object or an array - for recursive key conversion
        value = objectKeysToCamelCase(value);               // recursively update keys of any values that are also objects
      }
      camelCaseObject[_.camelCase(key)] = value;
    }
  )
  return camelCaseObject;
};

これでテスト [〜#〜] plunker [〜#〜]

:配列内のオブジェクトに対しても再帰的に機能します

19
goredwards

他に感謝します(lodashとES6で再帰関数):

import { camelCase } from 'lodash';

const camelizeKeys = (obj) => {
  if (Array.isArray(obj)) {
    return obj.map(v => camelizeKeys(v));
  } else if (obj !== null && obj.constructor === Object) {
    return Object.keys(obj).reduce(
      (result, key) => ({
        ...result,
        [camelCase(key)]: camelizeKeys(obj[key]),
      }),
      {},
    );
  }
  return obj;
};

テスト:

const obj = {
  'FirstName': 'John',
  'LastName': 'Smith',
  'BirthDate': new Date(),
  'ArrayTest': ['one', 'TWO', 3],
  'ThisKey': {
    'This-Sub-Key': 42
  }
}

console.log(JSON.stringify(camelizeKeys(obj)))

出力:

{  
   "firstName": "John",
   "lastName": "Smith",
   "birthDate": "2018-05-31T09:03:57.844Z",
   "arrayTest":[  
      "one",
      "TWO",
      3
   ],
   "thisKey":{  
      "thisSubKey": 42
   }
}
9
jeshio

LodashとES6を使用すると、すべてのキーがキャメルケースに再帰的に置き換えられます。

速記:

const camelCaseKeys = (obj) => ((!_.isObject(obj) && obj) || (_.isArray(obj) && obj.map((v) => camelCaseKeys(v))) || _.reduce(obj, (r, v, k) => ({ ...r, [_.camelCase(k)]: camelCaseKeys(v) }), {}));

拡張:

const camelCaseKeys = (obj) => {
  if (!_.isObject(obj)) {
    return obj;
  } else if (_.isArray(obj)) {
    return obj.map((v) => camelCaseKeys(v));
  }
  return _.reduce(obj, (r, v, k) => {
    return { 
      ...r, 
      [_.camelCase(k)]: camelCaseKeys(v) 
    };
  }, {});
};      
5
guatedude2

これは、 axios interceptors の優れたユースケースです。

基本的に、クライアントクラスを定義し、要求/応答データを変換するインターセプターの前後にアタッチします。

export default class Client {
    get(url, data, successCB, catchCB) {
        return this._perform('get', url, data, successCB, catchCB);
    }

    post(url, data, successCB, catchCB) {
        return this._perform('post', url, data, successCB, catchCB);
    }

    _perform(method, url, data, successCB, catchCB) {
        // https://github.com/axios/axios#interceptors
        // Add a response interceptor
        axios.interceptors.response.use((response) => {
            response.data = toCamelCase(response.data);
            return response;
        }, (error) => {
            error.data = toCamelCase(error.data);
            return Promise.reject(error);
        });

        // Add a request interceptor
        axios.interceptors.request.use((config) => {
            config.data = toSnakeCase(config.data);
            return config;
        }, (error) => {
            return Promise.reject(error);
        });

        return axios({
            method: method,
            url: API_URL + url,
            data: data,
            headers: {
                'Content-Type': 'application/json',
            },
        }).then(successCB).catch(catchCB)
    }
}

ここに Gist があり、React/axiosを使用したより長い例があります。

2
daino3

さて、私は挑戦を始めて、私はそれを理解したと思う:

var firstToLower = function(str) {
    return str.charAt(0).toLowerCase() + str.slice(1);
};

var firstToUpper = function(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
};

var mapToJsObject = function(o) {
    var r = {};
    $.map(o, function(item, index) {
        r[firstToLower(index)] = o[index];
    });
    return r;
};

var mapFromJsObject = function(o) {
    var r = {};
    $.map(o, function(item, index) {
        r[firstToUpper(index)] = o[index];
    });
    return r;
};


// Map to
var contacts = [
    {
        GivenName: "Matt",
        FamilyName: "Berry"
    },
    {
        GivenName: "Josh",
        FamilyName: "Berry"
    },
    {
        GivenName: "Thomas",
        FamilyName: "Berry"
    }
];

var mappedContacts = [];

$.map(contacts, function(item) {
    var m = mapToJsObject(item);
    mappedContacts.Push(m);
});

alert(mappedContacts[0].givenName);


// Map from
var unmappedContacts = [];

$.map(mappedContacts, function(item) {
    var m = mapFromJsObject(item);
    unmappedContacts.Push(m);
});

alert(unmappedContacts[0].GivenName);

プロパティコンバーター(jsfiddle)

トリックは、オブジェクトをオブジェクトプロパティの配列として処理することです。

2
KyorCode

試してみたい便利なライブラリを次に示します。 https://www.npmjs.com/package/camelize2

npm install --save camelize2でインストールするだけで、その後

const camelize = require('camelize2')

const response = {
   Contacts: [{ GivenName: "Matt", FamilyName:"Berry" }]
}

const camelizedResponse = camelize(response)
1
Denis Ivko

上記のプレーンjsソリューションに基づくこのソリューションは、loadashとパラメーターとして渡された場合は配列を保持しますを使用し、Keysのみを変更します

function camelCaseObject(o) {
    let newO, origKey, value
    if (o instanceof Array) {
        newO = []
        for (origKey in o) {
            value = o[origKey]
            if (typeof value === 'object') {
                value = camelCaseObject(value)
            }
            newO.Push(value)
        }
    } else {
        newO = {}
        for (origKey in o) {
            if (o.hasOwnProperty(origKey)) {
                newO[_.camelCase(origKey)] = o[origKey]
            }
        }
    }
    return newO
}

// Example
const obj = [
{'my_key': 'value'},
 {'Another_Key':'anotherValue'},
 {'array_key':
   [{'me_too':2}]
  }
]
console.log(camelCaseObject(obj))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
1
Gal Bracha

https://plnkr.co/edit/jtsRo9yU12geH7fkQ0WL?p=preview からの参照を使用してコードを更新しました。マップを使用して繰り返し処理できます)

function snakeToCamelCase(snake_case_object){
  var camelCaseObject;
  if (isPlainObject(snake_case_object)) {        
    camelCaseObject = {};
  }else if(isArray(snake_case_object)){
    camelCaseObject = [];
  }
  forEach(
    snake_case_object,
    function(value, key) {
      if (isPlainObject(value) || isArray(value)) {
        value = snakeToCamelCase(value);
      }
      if (isPlainObject(camelCaseObject)) {        
        camelCaseObject[camelCase(key)] = value;
      }else if(isArray(camelCaseObject)){
        camelCaseObject.Push(value);
      }
    }
  )
  return camelCaseObject;  
}
0
Nitin Gore

Lodashといくつかのes6 +機能で課題に取り組みましたreduce関数を使用した実装を次に示します。

function deeplyToCamelCase(obj) {
  return _.reduce(obj, (camelCaseObj, value, key) => {
    const convertedDeepValue = _.isPlainObject(value) || _.isArray(value)
      ? deeplyToCamelCase(value)
      : value;
    return { ...camelCaseObj, [_.camelCase(key)] : convertedDeepValue };
  }, {});
};
0

Goredwardsの答えに基づいて(配列フィールドを正しく処理しませんでした)

function objectKeysToCamelCase(snake_case_object) {
  let camelCaseObject = {}
  _.forEach(
    snake_case_object,
    function(value, key) {
      if (_.isPlainObject(value)) {
        value = objectKeysToCamelCase(value)
      } else if (_.isArray(value)) {
        value = value.map(v => _.isPlainObject(v) ? objectKeysToCamelCase(v) : v)
      }
      camelCaseObject[_.camelCase(key)] = value
    },
  )
  return camelCaseObject
}
0
Guy

配列またはオブジェクトを受け入れる汎用メソッドが必要でした。これは私が使用しているものです(KyorCodeのfirstToLower()実装を借りました):

function convertKeysToCamelCase(obj) {
    if (!obj || typeof obj !== "object") return null;

    if (obj instanceof Array) {
        return $.map(obj, function(value) {
            return convertKeysToCamelCase(value);
        });
    }

    var newObj = {};
    $.each(obj, function(key, value) {
        key = key.charAt(0).toLowerCase() + key.slice(1);
        if (typeof value == "object" && !(value instanceof Array)) {
          value = convertKeysToCamelCase(value);
        }
        newObj[key] = value;
    });

    return newObj;
};

呼び出しの例:

var contact = { GivenName: "Matt", FamilyName:"Berry" };

console.log(convertKeysToCamelCase(contact));
// logs: Object { givenName="Matt", familyName="Berry"}

console.log(convertKeysToCamelCase([contact]));
// logs: [Object { givenName="Matt", familyName="Berry"}]

console.log(convertKeysToCamelCase("string"));
// logs: null

console.log(contact);
// logs: Object { GivenName="Matt", FamilyName="Berry"}
0
Irving

これは私の意見です。 brandoncodeの実装よりも読みやすく、ネストが少なく、Date(ちなみに処理されません)やnullのようなEdgeのケースを処理するスペースがあります。

function convertPropertiesToCamelCase(instance) {
    if (instance instanceof Array) {
        var result = [];

        for (var i = 0; i < instance.length; i++) {
            result[i] = convertPropertiesToCamelCase(instance[i]);
        }

        return result;
    }

    if (typeof instance != 'object') {
        return instance;
    }

    var result = {};

    for (var key in instance) {
        if (!instance.hasOwnProperty(key)) {
            continue;
        }

        result[key.charAt(0).toLowerCase() + key.substring(1)] = convertPropertiesToCamelCase(instance[key]);
    }

    return result;
}
0
user3638471

Lodashを使用すると、次のように実行できます。

export const toCamelCase = obj => {
  return _.reduce(obj, (result, value, key) => {
    const finalValue = _.isPlainObject(value) || _.isArray(value) ? toCamelCase(value) : value;
    return { ...result, [_.camelCase(key)]: finalValue };
  }, {});
};
0
Vincent D'amour