2015-03-22 2 views
0

Мне нужно преобразовать строкуСкрытой строки объект в JavaScript

1. "user.member.staffAddress" 
2. "user.something" 

объекта:

1. { user: { member: { staffAddress: {} } } } 
2. { user: { something: {} } } 

ли кто-нибудь имеет элегантный способ, как это сделать? Он всегда должен быть объектом в объекте. Последнее свойство должно быть пустым.

ответ

1

Я написал утилиту, я думаю, что вы найдете полезными для этого: https://github.com/forms-js/forms-js/blob/master/source/utils/flatten.ts

Вот соответствующие биты. Это написано в TypeScript, но если вы удалите аннотации типа:, это действительный JavaScript.

/** 
* Writes a value to the location specified by a flattened key and creates nested structure along the way as needed. 
* 
* <p>For example, writing "baz" to the key 'foo.bar' would result in an object <code>{foo: {bar: "baz"}}</code>. 
* Writing 3 to the key 'foo[0].bar' would result in an object <code>{foo: [{bar: 3}]}</code>. 
*/ 
function write(value:any, flattenedKey:string, object:any):void { 
    var currentKey:any; 
    var keyIndexStart = 0; 

    for (var charIndex = 0, length = flattenedKey.length; charIndex < length; charIndex++) { 
    var character = flattenedKey.charAt(charIndex); 

    switch(character) { 
     case '[': 
     currentKey = flattenedKey.substring(keyIndexStart, charIndex); 

     createPropertyIfMissing_(currentKey, object, Array); 
     break; 
     case ']': 
     currentKey = flattenedKey.substring(keyIndexStart, charIndex); 
     currentKey = parseInt(currentKey); // Convert index from string to int 

     // Special case where we're targeting this object in the array 
     if (charIndex === length - 1) { 
      object[currentKey] = value; 
     } else { 

      // If this is the first time we're accessing this Array key we may need to initialize it. 
      if (!object[currentKey] && charIndex < length - 1) { 
      switch(flattenedKey.charAt(charIndex + 1)) { 
       case '[': 
       object[currentKey] = []; 
       break; 
       case '.': 
       object[currentKey] = {}; 
       break; 
      } 
      } 

      object = object[currentKey]; 
     } 
     break; 
     case '.': 
     currentKey = flattenedKey.substring(keyIndexStart, charIndex); 

     // Don't do anything with empty keys that follow Array indices (e.g. anArray[0].aProp) 
     if (currentKey) { 
      createPropertyIfMissing_(currentKey, object, Object); 
     } 
     break; 
     default: 
     continue; // Continue to iterate... 
     break; 
    } 

    keyIndexStart = charIndex + 1; 

    if (currentKey) { 
     object = object[currentKey]; 
    } 
    } 

    if (keyIndexStart < flattenedKey.length) { 
    currentKey = flattenedKey.substring(keyIndexStart, flattenedKey.length); 

    object[currentKey] = value; 
    } 
} 

/** 
* Helper method for initializing a missing property. 
* 
* @throws Error if unrecognized property specified 
* @throws Error if property already exists of an incorrect type 
*/ 
function createPropertyIfMissing_(key:string, object:any, propertyType:any):void { 
    switch(propertyType) { 
    case Array: 
     if (!object.hasOwnProperty(key)) { 
     object[key] = []; 
     } else if (!(object[key] instanceof Array)) { 
     throw Error('Property already exists but is not an Array'); 
     } 
     break; 
    case Object: 
     if (!object.hasOwnProperty(key)) { 
     object[key] = {}; 
     } else if (typeof object[key] !== 'object') { 
     throw Error('Property already exists but is not an Object'); 
     } 
     break; 
    default: 
     throw Error('Unsupported property type'); 
     break; 
    } 
} 

Чтобы быть справедливым, вы могли бы также рассмотреть проект написанный конкретно для этого - а не мой, в которой это лишь небольшая часть - что сказать, https://github.com/hughsk/flat

+1

Очень хорошее решение. Сложный, но +1 для записи значения последнему ключу в объекте. Я специально не задавал этот вопрос в своем вопросе, но я считаю это хорошим вариантом в моем проекте. – undefinedman

0

Итерация и добавить свойства и т.д. ...

function stringToObject(str) { 
 
    var obj = {}, arr = str.split('.'); 
 
    
 
    (function it(o) { 
 
     var key = arr.shift(); 
 
     o[key] = {}; 
 
     if (arr.length) it(o[key]); 
 
    }(obj)); 
 
    
 
    return obj; 
 
} 
 

 
var obj = stringToObject("user.member.staffAddress"); 
 

 
document.body.innerHTML = JSON.stringify(obj, null, 4);

+0

Это выглядит как более компактное решение, но оно не обрабатывает ребра (например, массивы). Не уверен, что автор беспокоился о них. – brianvaughn

0

подход преобразования строки:

var str = 'user.member.staffAddress' 
var str_arr = str.split('.') 
var obj = JSON.parse(
    '{ "' + str_arr.join('": { "') + '": {}' 
    + Array(str_arr.length+1).join(' }') 
) 
console.log(obj) 
// { "user": { "member": { "staffAddress": {} } } } 
  1. Разделить строку.
  2. Соединительные элементы с ": { ".
  3. Оберните новую строку с помощью { " и ": {}, а затем length количество закрывающих фигурных скобок.
  4. Провести финальную строку как объект JSON.

JSFiddle Demo

Смежные вопросы