sort object properties and JSON.stringify

后端 未结 22 2155
南方客
南方客 2020-11-28 05:44

My application has a large array of objects, which I stringify and save them to the disk. Unfortunately, when the objects in the array are manipulated, and sometimes replac

相关标签:
22条回答
  • 2020-11-28 06:26

    Works with lodash, nested objects, any value of object attribute:

    function sort(myObj) {
      var sortedObj = {};
      Object.keys(myObj).sort().forEach(key => {
        sortedObj[key] = _.isPlainObject(myObj[key]) ? sort(myObj[key]) : myObj[key]
      })
      return sortedObj;
    }
    JSON.stringify(sort(yourObj), null, 2)
    

    It relies on Chrome's and Node's behaviour that the first key assigned to an object is outputted first by JSON.stringify.

    0 讨论(0)
  • 2020-11-28 06:26

    Surprised nobody has mentioned lodash's isEqual function.

    Performs a deep comparison between two values to determine if they are equivalent.

    Note: This method supports comparing arrays, array buffers, booleans, date objects, error objects, maps, numbers, Object objects, regexes, sets, strings, symbols, and typed arrays. Object objects are compared by their own, not inherited, enumerable properties. Functions and DOM nodes are compared by strict equality, i.e. ===.

    https://lodash.com/docs/4.17.11#isEqual

    With the original problem - keys being inconsistently ordered - it's a great solution - and of course it will just stop if it finds a conflict instead of blindly serializing the whole object.

    To avoid importing the whole library you do this:

    import { isEqual } from "lodash-es";
    

    Bonus example: You can also use this with RxJS with this custom operator

    export const distinctUntilEqualChanged = <T>(): MonoTypeOperatorFunction<T> => 
                                                    pipe(distinctUntilChanged(isEqual));
    
    0 讨论(0)
  • 2020-11-28 06:27

    Update 2018-7-24:

    This version sorts nested objects and supports array as well:

    function sortObjByKey(value) {
      return (typeof value === 'object') ?
        (Array.isArray(value) ?
          value.map(sortObjByKey) :
          Object.keys(value).sort().reduce(
            (o, key) => {
              const v = value[key];
              o[key] = sortObjByKey(v);
              return o;
            }, {})
        ) :
        value;
    }
    
    
    function orderedJsonStringify(obj) {
      return JSON.stringify(sortObjByKey(obj));
    }
    

    Test case:

      describe('orderedJsonStringify', () => {
        it('make properties in order', () => {
          const obj = {
            name: 'foo',
            arr: [
              { x: 1, y: 2 },
              { y: 4, x: 3 },
            ],
            value: { y: 2, x: 1, },
          };
          expect(orderedJsonStringify(obj))
            .to.equal('{"arr":[{"x":1,"y":2},{"x":3,"y":4}],"name":"foo","value":{"x":1,"y":2}}');
        });
    
        it('support array', () => {
          const obj = [
            { x: 1, y: 2 },
            { y: 4, x: 3 },
          ];
          expect(orderedJsonStringify(obj))
            .to.equal('[{"x":1,"y":2},{"x":3,"y":4}]');
        });
    
      });
    

    Deprecated answer:

    A concise version in ES2016. Credit to @codename , from https://stackoverflow.com/a/29622653/94148

    function orderedJsonStringify(o) {
      return JSON.stringify(Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {}));
    }
    
    0 讨论(0)
  • 2020-11-28 06:28

    You can sort object by property name in EcmaScript 2015

    function sortObjectByPropertyName(obj) {
        return Object.keys(obj).sort().reduce((c, d) => (c[d] = obj[d], c), {});
    }
    
    0 讨论(0)
提交回复
热议问题