0

我有一个 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

4 回答 4

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));
    });
  });
于 2013-06-05T01:23:38.083 回答
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>");
  }
}
于 2013-06-05T01:13:44.140 回答
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上检查它

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

但是您可以肯定地对其进行修改和优化...

于 2013-06-05T01:15:52.790 回答
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);
  });
});
于 2013-06-05T01:20:35.703 回答