处理嵌套的JSON数据时,避免嵌套每个循环

时间:2013-06-05 01:00:26

标签: javascript json

我有一个JSON对象:

{
   "custom_sql_rule":[
      {
         "custom_sql":[
            "Should start with a Select",
            "Should not contain ;",
            "Some other error"
         ],
         "something_else":[
            "Error",
            "Should not contain ;",
            "Some other error"
         ]
      }
   ],
   "someother_rule":[
      {
         "sdfsdf":[
            "Should start with a Select",
            "Should not contain ;",
            "Some other error"
         ],
         "sdfsdf":[
            "Error",
            "Should not contain ;",
            "Some other error"
         ]
      }
   ]
}

我需要将每个字符串错误附加到div。我很快就掀起了这个问题:

var errorMessages = function(errors, errorsContainer) {
  $.each(errors, function(index, value) {
    $.each(value, function(i, v) {
      $.each(v, function(ia, va) {
        $.each(va, function(iab, vab) {
          errorsContainer.append($("<div></div>").addClass(index).text(vab));
        })
      })
    })
  });
};

太可怕了。是否有一种更好的处理JSON的方式?注意,我不能真正使用键名。

4 个答案:

答案 0 :(得分:2)

这是一个解决方案,它将遍历对象和数组树,识别每个字符串。

function eachLeafString(dataObject, callbackMethod) {
    if(typeof dataObject == 'string') {
        callbackMethod(dataObject);
    }
    else if (Object.prototype.toString.call( dataObject ) === '[object Array]') {
        $.each(dataObject, function(index, elem) { eachLeafString(elem, callbackMethod); });
    }
    else {
        for(var propertyName in dataObject) {
            eachLeafString(dataObject[propertyName], callbackMethod);
        }
    }
}

有关此工作的示例:http://jsfiddle.net/e6XN7/3/

如果要使用第一级节点的索引,可以按如下方式使用它:

  $.each(errors, function(index, value) {
    eachLeafString(value, function(vab) {
         errorsContainer.append($("<div></div>").addClass(index).text(vab));
    });
  });

答案 1 :(得分:1)

JSON是“只是”javascript对象文字。您可以跳过jQuery调用,只需在parse之后直接引用对象和数组。

obj.custom_sql_rule[0].something_else[0];

当然,你的JSON有点奇怪。如果可能的话,不要随意混合对象{}和数组[]。当您具有相同对象或基本数据的列表时使用后者,而当您具有命名属性时使用前者。一旦你有了一个有效的javascript对象,你就可以遍历它的属性。

for(var sqlProp in jsonObj) {
  if(jsonObj[sqlProp].error) {
    errorsContainer.append("<div>" + jsonObj[sqlProp].error + "</div>");
  }
}

答案 2 :(得分:1)

尝试这样的递归函数:

function errorMessages(errors,errorsContainer,errorclass)
{

  if ( typeof errors == "string")
    errorsContainer.append($("<div></div>").addClass(errorclass).text(errors));
  else
  {
    $.each(errors, function(classname, value)
          {

           errorMessages(value,errorsContainer,(typeof errorclass == "undefined") ? classname : errorclass );                           
      });
   }
};

jsfiddle

上查看

当你调用你的函数时,不要传递第三个参数,他将为null,所以你的类将从你的JSON中获取。如果你在你的param中传递一个类,它将覆盖你的JSON中的一个类。你选择:)

但你可以肯定地修改和优化它......

答案 3 :(得分:0)

您可以修改JSON本身的结构,使其“更宽/更平坦”而不是“更深”,而不是修改通过JSON运行的代码。

//errors

[
  {
    "error" : "custom_sql_error",
    "subcategory" : "custom_sql",
    "messages" : [
      "Should start with a Select",
      "Should not contain ;",
      "Some other error"
    ]
  },
  {
    "error" : "custom_sql_error",
    "subcategory" : "something_else",
    "messages" : [
      "Error",
      "Should not contain ;",
      "Some other error"
    ]
  },
  {
    "error" : "someother_rule",
    "subcategory" : "sdfsdf",
    "messages" : [
      "Should start with a Select",
      "Should not contain ;",
      "Some other error"
    ]
  },
  {
    "error" : "someother_rule",
    "subcategory" : "sdfsdf",
    "messages" : [
      "Error",
      "Should not contain ;",
      "Some other error"
    ]
  }
]

这样,你就像这样循环

$.each(errors, function(index, value) {
  $.each(value.messages, function (index, message){
    $("<div/>").addClass(index).text(message).appendTo(errorsContainer);
  });
});