0

I have a JSON object:

{
   "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"
         ]
      }
   ]
}

I need to append each string error to a div. I quickly whipped this up:

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));
        })
      })
    })
  });
};

It's terrible. Is there a nicer way of handling JSON formed like this? NOTE, I cannot really use keynames.

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/

第 1 レベルのノードのインデックスを使用する場合は、次のように使用できます。

  $.each(errors, function(index, value) {
    eachLeafString(value, function(vab) {
         errorsContainer.append($("<div></div>").addClass(index).text(vab));
    });
  });
于 2013-06-05T01:23:38.083 に答える
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で確認してください

関数を呼び出すときは、3 番目の引数を渡さないでください。彼は null になるため、クラスは JSON から取得されます。パラメータでクラスを渡すと、JSON のクラスが上書きされます。選んで :)

しかし、確実に変更して最適化することはできます...

于 2013-06-05T01:15:52.790 に答える
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 に答える
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 に答える