【问题标题】:Recursively convert an object fields from snake case to camelCase递归地将对象字段从蛇案例转换为骆驼案例
【发布时间】:2020-05-03 07:06:58
【问题描述】:

我有一个这样的对象(snake_case 中的字段)

const obj = {
  vt_core_random: {
    user_details: {
      first_name: "xyz",
      last_name: "abc",
      groups: [
        {
          id: 1,
          group_type: "EXT"
        },
        {
          id: 2,
          group_type: "INT"
        }
      ],
      address_type: {
        city_name: "nashik",
        state: {
          code_name: "MH",
          name: "Maharashtra"
        }
      }
    }
  }
};

我想递归地将其字段转换为camelCase,所以下面给出了预期的输出

const obj = {
  vtCoreRandom: {
    userDetails: {
      firstName: "xyz",
      lastName: "abc",
      groups: [
        {
          id: 1,
          groupType: "EXT"
        },
        {
          id: 2,
          groupType: "INT"
        }
      ],
      addressType: {
        cityName: "LMN",
        state: {
          codeName: "KOP",
          name: "PSQ"
        }
      }
    }
  }
};

我尝试使用 mapKeys(),但我无法理解这个递归部分。非常感谢任何帮助。如果它使过程更简单,我也可以使用lodash

【问题讨论】:

    标签: javascript object recursion lodash


    【解决方案1】:

    您可以使用 lodash 的 _.transform() 创建一个递归函数,该函数迭代键并将它们转换为 _.camelCase() 的驼峰式大小写。 Transform也可以处理数组,所以如果被迭代的对象(target)是数组,我们就不需要改key了。

    const camelize = obj => _.transform(obj, (acc, value, key, target) => {
      const camelKey = _.isArray(target) ? key : _.camelCase(key);
      
      acc[camelKey] = _.isObject(value) ? camelize(value) : value;
    });
    
    const obj = {"vt_core_random":{"user_details":{"first_name":"xyz","last_name":"abc","groups":[{"id":1,"group_type":"EXT"},{"id":2,"group_type":"INT"}],"address_type":{"city_name":"nashik","state":{"code_name":"MH","name":"Maharashtra"}}}}};
    
    const result = camelize(obj);
    
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

    【讨论】:

    • 打字稿版本:import { camelCase, isArray, transform, isObject } from "lodash"; const camelize = (obj: Record<string, unknown>) => transform(obj, (result: Record<string, unknown>, value: unknown, key: string, target) => { const camelKey = isArray(target) ? key : camelCase(key); result[camelKey] = isObject(value) ? camelize(value as Record<string, unknown>) : value; });
    【解决方案2】:

    你可以试试这样的:

    const obj = {
      vt_core_random: {
        user_details: {
          first_name: "xyz",
          last_name: "abc",
          groups: [
            {
              id: 1,
              group_type: "EXT"
            },
            {
              id: 2,
              group_type: "INT"
            }
          ],
          address_type: {
            city_name: "nashik",
            state: {
              code_name: "MH",
              name: "Maharashtra"
            }
          }
        }
      }
    };
    
    const toCamel = (str) => {
      return str.replace(/([-_][a-z])/ig, ($1) => {
        return $1.toUpperCase()
          .replace('-', '')
          .replace('_', '');
      });
    };
    
    const isObject = function (obj) {
      return obj === Object(obj) && !Array.isArray(obj) && typeof obj !== 'function';
    };
    
    const keysToCamel = function (obj) {
      if (isObject(obj)) {
        const n = {};
    
        Object.keys(obj)
          .forEach((k) => {
            n[toCamel(k)] = keysToCamel(obj[k]);
          });
    
        return n;
      } else if (Array.isArray(obj)) {
        return obj.map((i) => {
          return keysToCamel(i);
        });
      }
      
      return obj;
    };
    
    console.log(keysToCamel(obj));

    【讨论】:

      【解决方案3】:

      对于所有使用 lodash 的人,我已经操纵了接受的答案,因为 lodash 已经包含了诸如 isArray isObject camelCase 之类的实用程序函数

      所以代码简化为这个。 :)

      function keysToCamel(obj) {
        if (isPlainObject(obj)) {
          const n = {};
          Object.keys(obj).forEach(k => (n[camelCase(k)] = keysToCamel(obj[k])));
          return n;
        } else if (isArray(obj)) obj.map(i => keysToCamel(i));
        return obj;
      }
      

      【讨论】:

      • 这不起作用,因为 lodash 中的 isObject 为数组 Checks if value is the language type of Object. (e.g. arrays, functions, objects, regexes, new Number(0), and new String('')) 返回 true
      • @cip123 修复了这个问题。
      • 打字稿版本:import { isPlainObject, camelCase, isArray } from "lodash"; function convertKeysToCamelCase(obj: unknown): unknown { if (isPlainObject(obj)) { const n = {}; Object.keys(obj as object).forEach( (k) => (n[camelCase(k)] = convertKeysToCamelCase((obj as object)[k])) ); return n; } else if (isArray(obj)) obj.map((i) => convertKeysToCamelCase(i)); return obj; }
      【解决方案4】:
      const obj = {
        vt_core_random: {
          user_details: {
            first_name: "xyz",
            last_name: "abc",
            groups: [
              {
                id: 1,
                group_type: "EXT"
              },
              {
                id: 2,
                group_type: "INT"
              }
            ],
            address_type: {
              city_name: "nashik",
              state: {
                code_name: "MH",
                name: "Maharashtra"
              }
            }
          }
        }
      };
      
      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 = _.camelCase(origKey)
              value = o[origKey]
              if (value instanceof Array || (value !== null && value.constructor === Object)) {
                value = toCamel(value)
              }
              newO[newKey] = value
            }
          }
        }
        return newO
      }
      
      console.log(toCamel(obj));    const obj = {
        vt_core_random: {
          user_details: {
            first_name: "xyz",
            last_name: "abc",
            groups: [
              {
                id: 1,
                group_type: "EXT"
              },
              {
                id: 2,
                group_type: "INT"
              }
            ],
            address_type: {
              city_name: "nashik",
              state: {
                code_name: "MH",
                name: "Maharashtra"
              }
            }
          }
        }
      };
      
      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 = _.camelCase(origKey)
              value = o[origKey]
              if (value instanceof Array || (value !== null && value.constructor === Object)) {
                value = toCamel(value)
              }
              newO[newKey] = value
            }
          }
        }
        return newO
      }
      
      console.log(toCamel(obj));
      

      我在这段代码中使用了 lodash。

      【讨论】:

        【解决方案5】:

        你可以用一种相当通用的方式来做到这一点,编写一个接受任意键转换函数的函数,并返回一个接受一个对象并返回一个具有相同结构但键已转换的对象。这基本上并不比专门编写代码来实现键的骆驼化更难。

        这是一种方法:

        const fixKeys = (fn) => (obj) => Object .fromEntries (
          Object .entries (obj) .map (([k, v]) => [
            fn(k), 
            Array .isArray (v) ? v .map (fixKeys (fn)) : typeof v == 'object' ? fixKeys (fn) (v) : v
          ])
        )
        
        const camelCase = (s) => s.replace(/_(.)/g, (s, c) => c.toUpperCase())
        
        const camelizeKeys = fixKeys (camelCase)
        
        const obj = {vt_core_random: {user_details: {first_name: "xyz", last_name: "abc", groups: [{id: 1, group_type: "EXT"}, {id: 2, group_type: "INT"}], address_type: { city_name: "nashik", state: {code_name: "MH",  name: "Maharashtra"}}}}}
        
        console .log (camelizeKeys (obj))

        如果Object.fromEntries 在您的环境中不可用,则很容易填充或替换。此外,它被标记为“lodash”,如果您已经在使用它,您可能希望将这里的一些自定义功能替换为 lodash 函数,包括 camelCase 函数以及数组和对象测试。或者不,因为这已经相当简单了。

        【讨论】:

          【解决方案6】:

          对于那些使用打字稿的人。我在这个问题的已接受答案中添加了类型。

          const toCamel = (str: string): string => {
            return str.replace(/([_-][a-z])/gi, ($1: string) => {
              return $1.toUpperCase().replace('-', '').replace('_', '');
            });
          };
          
          const isArray = function (
            input: Record<string, unknown> | Record<string, unknown>[] | unknown
          ): input is Record<string, unknown>[] {
            return Array.isArray(input);
          };
          
          const isObject = function (
            obj: Record<string, unknown> | Record<string, unknown>[] | unknown
          ): obj is Record<string, unknown> {
            return (
              obj === Object(obj) && !Array.isArray(obj) && typeof obj !== 'function'
            );
          };
          
          const camelize = function <T>(input: T): T {
            return (function recurse<
              K extends Record<string, unknown> | Record<string, unknown>[] | unknown
            >(input: K): K {
              if (isObject(input)) {
                return Object.keys(input).reduce((acc, key) => {
                  return Object.assign(acc, { [toCamel(key)]: recurse(input[key]) });
                }, {} as K);
              } else if (isArray(input)) {
                return input.map((i) => recurse(i)) as K;
              }
              return input;
            })(input);
          };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-10-30
            • 2020-02-10
            • 1970-01-01
            • 2022-06-11
            • 1970-01-01
            • 2016-01-16
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多