Получить значение объекта JSON с внутренними объектами по имени поля формы HTML без eval - PullRequest
2 голосов
/ 22 ноября 2010

У меня такая проблема Преобразование поля формы HTML в объект JSON с внутренними объектами , но в другом направлении.

Это ответ JSON Object с сервера:

{
    company : "ACME, INC.",
    contact : {
        firstname : "Daffy", 
        lastname : "Duck"
    }
}

А это HTML-форма:

<form id="myform">
    Company: <input type="text" name="company" />
    First Name: <input type="text" name="contact.firstname" />
    Last Name: <input type="text" name="contact.lastname" />
</form>

А это (псевдо) код:

var aFormFields; 

for (var i = 0, iMax = aFormFields.length; i < iMax; i++) {

    var sFieldName = aFormFields[i].getAttribute('name');
    eval("sFieldValue = oResponse."+sFieldName);

}

Хорошо, мое решение работает, но я ищу хороший способ убрать зловредного кода из кода. И решение также должно работать для полей формы с любым количеством точек в имени поля.

Ответы [ 5 ]

4 голосов
/ 22 ноября 2010

Вместо:

eval("sFieldValue = oResponse."+sFieldName); 

Использовать для полей с одной точкой:

sFieldValue = oResponse[sFieldName];

Получит значение через ключ.

Теперь, если вам нужно больше, вам нужно сделать следующее:

  1. Разделить sFieldName на .
  2. Зацикливайтесь на этом массиве и заходите в oResponse, пока не достигнете желаемого значения

Код может выглядеть следующим образом:

var node = oResponse, parts = sFieldName.split('.');
while(parts.length > 0) {
   node = node[parts.shift()];
}
// node will now have the desired value

Дополнительная информация по «Операторам-членам»:
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Member_Operators

2 голосов
/ 22 ноября 2010

Это работает для одного свойства:

sFieldValue = oResponse[sFieldName]

Но это не будет работать для вложенных данных, таких как contact.firstname. Для этого разделите имя по точкам и используйте цикл по каждому имени:

var aFormFields; 

for (var i = 0, iMax = aFormFields.length; i < iMax; i++) {

    var aFieldNameParts = aFormFields[i].getAttribute('name').split(".");
    var oFieldValue = oResponse;
    for(var j=0; j<aFieldNameParts.length; j++) {
        oFieldValue = oFieldValue[aFieldNameParts[j]];
    }
    var sFieldValue = oFieldValue;
}

Примечание: если свойство не существует, произойдет ошибка. Возможно, вы захотите проверить, существует ли oFieldValue[ aFieldNameParts[j] ] или нет.

0 голосов
/ 06 февраля 2013

пожалуйста, отнеситесь к этому как к комбинации ответа и вопроса:)

В настоящее время я пытаюсь заставить мой сервер jsonify данных, которые я получаю из формы, такой же, как вы ...

в моем случае форма в конце создаст объект json с несколькими подобъектами, которые могут иметь подобъекты, которые могут иметь ... также.

глубина зависит от пользователя, поэтому я должен иметь возможностьподдерживать бесконечную рекурсию.

мое "решение" пока что просто кажется неправильным, но оно правильно выполняет свою работу, функция getRequestBody получает объект req.body из expressjs, в основном это объект со следующим отображением:

{
  "ridic-ulously-deep-subobject": "value",
  "ridic-ulously-deep-subobject2": "value",
  "ridic-ulously-deep2-subobject3": "value",
}

используется следующий html:

<form>
    <input name="ridic-ulously-long-class-string" value="my value" />
  </form>

и функция javascript (которая должна работать в общем случае, передайте ей объект req.body, как указано выше, и он вернет jsonобъект):

function getRequestBody(reqB){

  var reqBody = {};

  for(var keys in reqB) {

    var keyArr = keys.split('-');

    switch(keyArr.length){
      case 1:
        if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
        reqBody[keyArr[0]] = reqB[keys];
      break;

      case 2:
        if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
        if(!reqBody[keyArr[0]][keyArr[1]]) reqBody[keyArr[0]][keyArr[1]] = {};

        reqBody[keyArr[0]][keyArr[1]] = reqB[keys];
      break;

      case 3:
        if(!reqBody[keyArr[0]]) reqBody[keyArr[0]] = {};
        if(!reqBody[keyArr[0]][keyArr[1]]) reqBody[keyArr[0]][keyArr[1]] = {};
        if(!reqBody[keyArr[0]][keyArr[1]][keyArr[2]]) reqBody[keyArr[0]][keyArr[1]][keyArr[2]] = {};

        reqBody[keyArr[0]][keyArr[1]][keyArr[2]] = reqB[keys];
      break;

      case 4:

      // ...
      //and so on, always one line longer
  }

    return reqBody;
}

это просто кажется неправильным, и сейчас оно охватывает только 5 уровней подобъектов, может случиться так, что у приложения будет достаточно функциональности, чтобы достичь семиХотя даже десять уровней.

это должно быть обычной проблемой, но мои поисковые усилия ничего не дали в течение 10 минут, что обычно означает, что я пропускаю некоторые ключевые слова или что нетжизнеспособное решение [пока] (которое я не могу действительно вообразить в этом случае).

есть ли кто-то, у кого достаточно воображения и логики, чтобы его можно было разгадать, или мне просто нужно расширить эту функцию еще большим количеством беспорядка, чтобы я опустился до 10 возможных подуровней?

iдумаю, что в конечном итоге это не будет иметь большого значения для производительности, но мне бы очень хотелось НЕ создавать этого ужасного бегемота: D

получай удовольствие

jascha

0 голосов
/ 22 ноября 2010

Предполагая, что ваша схема именования последовательна, вы можете конвертировать точечные обозначения в подписки. Вам придется разделить имя поля по периоду и итерировать или рекурсировать по токенам, конвертируя каждое в индекс. Конечно, это предполагает, что oResponse всегда содержит значение для каждого поля.

for (var i = 0; i < aFormFields.length; i++) {
    var sFieldName = aFormFields[i].getAttribute('name');
    var tokens = sFieldName.split('.');
    var cur = oResponse;

    for (var j = 0; j < tokens.length; j++) {
        cur = cur[tokens[j]];
    }

    sFieldValue = cur;
}
0 голосов
/ 22 ноября 2010

Хотя это возможно, я бы не зацикливался на полях ввода, а только на объекте JSON:

function fillForm (form, data, prefix) {
  prefix = prefix ? prefix + "." : "";
  for (var x in data) {
    if (typeof data[x] === "string") {
      var input = form.elements[prefix + x];
      if (input)
        input.value = data[x];
    } else
      fillForm(form, data[x], prefix + x);
  }
}

fillForm(document.getElementById("myform"), oResponse);

(непроверенные)

...