0

I would like to get an object as such:

let params_ = {
  filters: {
    orderId: null,
    status: ['rejected', 'accepted'],
    orderStatus: 'A',
    a: {
      c: 'deepFilter'
    }
  },
  page: {
    limit: 15,
    offset: 0
  }
}

and transform it into:

{
  filters[orderId]: null,
  filters[status]: ['rejected', 'acepted'],
  filters[orderStatus]: 'A',
  filters[a.c]: 'deepFilter',
  page[limit]: 15,
  page[offset]: 0,
}

I was able to go into a two level and getting the result as desired but Im having a problem knowing where I should make the recursive call to be able to call deep nested levels.

So far I have tried the following:

let params_ = {
  filters: {
    orderId: null,
    status: ['rejected', 'accepted'],
    orderStatus: 'A',
    a: {
      c: 'a'
    }
  },
  page: {
    limit: 15,
    offset: 0
  }
}

function paramsSerializer(parameters) {
  let finalParameters = {};

  for (let key in parameters) {
    if (parameters.hasOwnProperty(key)) {
      if (typeof parameters[key] === 'object' && parameters[key] !== null) {
        finalParameters = {
          ...finalParameters,
          ...constructParameterFromObject(parameters[key], key)
        }
      }
    }
  }

  console.log(finalParameters);
}

function constructParameterFromObject(object, prepend = null) {
  let finalParameters = {};

  for (let key in object) {
    if (object.hasOwnProperty(key)) {
      finalParameters = {
        ...finalParameters,
        ...{
          [`${prepend}[${key}]`]: object[key]
        }
      }
    }
  }

  return finalParameters;
}

paramsSerializer(params_);

You can have a live example over here: https://codesandbox.io/s/angry-dream-sl0gr Any light would be highly appreciated. Thank you very much for the help in advance

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
  • Why is it `filters[a.c]` and not `filters[a][c]`? – adiga Dec 06 '19 at 11:45
  • The implementation of the JSON:API in our workplace is made by referencing deep relationships by a dot. Example making a request to a Posts endpoint: `filters[author.name]=masterofnothing` – masterofnothing Dec 06 '19 at 11:55
  • This has answers which will convert the keys to `filters.a.c`: [Fastest way to flatten / un-flatten nested JSON objects](https://stackoverflow.com/questions/19098797) – adiga Dec 06 '19 at 12:02

2 Answers2

0

You can do something like this:

let params_ = {
  filters: {
    orderId: null,
    status: ['rejected', 'accepted'],
    orderStatus: 'A',
    a: {
      c: 'deepFilter'
    }
  },
  page: {
    limit: 15,
    offset: 0
  }
}

function paramsSerializer(params, prefix) {
 return Object.entries(params).reduce((a, [key, value]) => {
   let fullKey = key;
   if (prefix) {
     if (prefix.includes('[')) {
       fullKey = prefix.replace(']', `.${key}]`);
     } else {
       fullKey = `${prefix}[${key}]`;
     }
   }

   if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
     a = {...a, ...paramsSerializer(value, fullKey)};
   } else {
     a = {...a, [fullKey]: value};
   }
   return a;
 }, {});
}

const ret = paramsSerializer(params_);
console.log(ret);

This will only work if the original object's keys don't contain the [ and ] characters. There is probably another way of constructing the new keys without using String.replace(..).

Titus
  • 22,031
  • 1
  • 23
  • 33
0
let params = {
    filters: {
        orderId: null,
        status: ['rejected', 'accepted'],
        orderStatus: 'A',
        a: {
            c: 'deepFilter',
            d: 'lightFilters',
            e: {
                f: ['Hi', 'There'],
                g: 100
            }
        }
    },
    page: {
        limit: 15,
        offset: 0
    }
}
function paramsSerializerRecursive(originalParameters, parentName){
    // Store (key,value) pairs
    let key_value_pairs = []
    parentName !== ''?parentName=parentName+'.':null;
    for (let key in originalParameters) {
        // If value is null
        if(originalParameters[key] === null)
            key_value_pairs.push([parentName+key, null])
        // Object but not array
        else if(typeof(originalParameters[key]) === 'object' && !Array.isArray(originalParameters[key])) {
            // Recursively get all (key,value) pairs for child object
            let child_pairs = paramsSerializerRecursive(originalParameters[key], parentName+key)
            // Add them to current (key,value) pairs list
            for(let pair of child_pairs)
                key_value_pairs.push(pair)
        }
        // Anything else
        else
            key_value_pairs.push([parentName+key, originalParameters[key]])
    }
    return key_value_pairs
}

function paramsSerializer(params){
    let serializedParams = {}
    for(let key in params){
        let key_value_pairs = paramsSerializerRecursive(params[key],'')
        for(let pair of key_value_pairs)
            serializedParams[String(key)+'['+pair[0]+']'] = pair[1]
    }
    console.log(serializedParams);
}

paramsSerializer(params);

Output

{ 
  'filters[orderId]': null,
  'filters[status]': [ 'rejected', 'accepted' ],
  'filters[orderStatus]': 'A',
  'filters[a.c]': 'deepFilter',
  'filters[a.d]': 'lightFilters',
  'filters[a.e.f]': [ 'Hi', 'There' ],
  'filters[a.e.g]': 100,
  'page[limit]': 15,
  'page[offset]': 0
}
Ajay Dabas
  • 1,404
  • 1
  • 5
  • 15