9

ありえない状況に陥っています。私は宇宙からの JSON を持っています (彼らがそれを変更する方法はありません)。これがJSONです

{
    user:'180111',
    title:'I\'m sure "E pluribus unum" means \'Out of Many, One.\' \n\nhttp://en.wikipedia.org/wiki/E_pluribus_unum.\n\n\'',
    date:'2007/01/10 19:48:38',
    "id":"3322121",
    "previd":112211,
    "body":"\'You\' can \"read\" more here [url=http:\/\/en.wikipedia.org\/?search=E_pluribus_unum]E pluribus unum[\/url]'s. Cheers \\*/ :\/",
    "from":"112221",
    "username":"mikethunder",
    "creationdate":"2007\/01\/10 14:04:49"
}

「有効な JSON にはほど遠い」と私は言いました。そして、彼らの反応は「うーん!しかし、Javascriptは文句なしにそれを読むことができます」でした

<html>
<script type="text/javascript">
    var obj = {"PUT JSON FROM UP THERE HERE"};

    document.write(obj.title);
    document.write("<br />");
    document.write(obj.creationdate + " " + obj.date);
    document.write("<br />");
    document.write(obj.body);
    document.write("<br />");
</script>
<body>
</body>
</html>

問題

この文字列を .NET(4) 経由で読み取って解析することになっていますが、Json.orgの C# セクションで言及されている 14 のライブラリのうち 3 つが壊れていました (残りは試していません)。問題を解決するために、次の関数を作成して、一重引用符と二重引用符の問題を修正しました。

public static string JSONBeautify(string InStr){
    bool inSingleQuote = false;
    bool inDoubleQuote = false;
    bool escaped = false;

    StringBuilder sb = new StringBuilder(InStr);
    sb = sb.Replace("`", "<°)))><"); // replace all instances of "grave accent" to "fish" so we can use that mark later. 
                                        // Hopefully there is no "fish" in our JSON
    for (int i = 0; i < sb.Length; i++) {
        switch (sb[i]) {

            case '\\':
                if (!escaped)
                    escaped = true;
                else 
                    escaped = false;
                break;
            case '\'':
                if (!inSingleQuote && !inDoubleQuote) {
                    sb[i] = '"';            // Change opening single quote string markers to double qoute
                    inSingleQuote = true;
                } else if (inSingleQuote && !escaped) {
                    sb[i] = '"';            // Change closing single quote string markers to double qoute
                    inSingleQuote = false;
                } else if (escaped) {
                    escaped = false;
                }
                break;
            case '"':
                if (!inSingleQuote && !inDoubleQuote) {
                    inDoubleQuote = true;   // This is a opening double quote string marker
                } else if (inSingleQuote && !escaped) {
                    sb[i] = '`';            // Change unescaped double qoute to grave accent
                } else if (inDoubleQuote && !escaped) {
                    inDoubleQuote = false; // This is a closing double quote string marker
                } else if (escaped) {
                    escaped = false;
                }
                break;
            default:
                escaped = false;
                break;
        }
    }
    return sb.ToString()
        .Replace("\\/", "/")        // Remove all instances of escaped / (\/) .hopefully no smileys in string
        .Replace("`", "\\\"")       // Change all "grave accent"s to escaped double quote \"
        .Replace("<°)))><", "`")   // change all fishes back to "grave accent"
        .Replace("\\'","'");        // change all escaped single quotes to just single quote
}

これで、JSONlint は属性名についてのみ文句を言うようになり、JSON.NET ライブラリと SimpleJSON ライブラリの両方を使用して JSON を解析できるようになりました。

質問

私のコードは、前述の JSON を修正する最良の方法ではないと確信しています。私のコードが壊れる可能性のあるシナリオはありますか? これを行うより良い方法はありますか?

4

3 に答える 3

8

これを JavaScript で実行する必要があります。.netで JavaScript パーサーを起動します。文字列を JavaScript への入力として与え、JavaScript のネイティブJSON.stringifyを使用して変換します。

obj = {
    "user":'180111',
    "title":'I\'m sure "E pluribus unum" means \'Out of Many, One.\' \n\nhttp://en.wikipedia.org/wiki/E_pluribus_unum.\n\n',
    "date":'2007/01/10 19:48:38',
    "id":"3322121",
    "previd":"112211",
    "body":"\'You\' can \"read\" more here [url=http:\/\/en.wikipedia.org\/?search=E_pluribus_unum]E pluribus unum[\/url]'s. Cheers \\*/ :\/",
    "from":"112221",
    "username":"mikethunder",
    "creationdate":"2007\/01\/10 14:04:49"
}

console.log(JSON.stringify(obj));
document.write(JSON.stringify(obj));

取得した文字列 (またはオブジェクト) は有効な JSON ではなく、JSON ライブラリで解析できないことに注意してください。最初に有効な JSON に変換する必要があります。ただし、有効な JavaScript です。

この回答を完了するには: JavaScriptSerializerin .Netを使用できます。このソリューションには、次のアセンブリが必要です。

  • System.Net
  • System.Web.Script.Serialization

    var webClient = new WebClient();
    string readHtml = webClient.DownloadString("uri to your source (extraterrestrial)");
    var a = new JavaScriptSerializer();
    
    Dictionary<string, object> results = a.Deserialize<Dictionary<string, object>>(readHtml);
    
于 2015-02-07T14:54:05.290 に答える
2

これはどう:

 string AlienJSON = "your alien JSON";
 JavaScriptSerializer js = new JavaScriptSerializer();
 string ProperJSON = js.Serialize(js.DeserializeObject(AlienJSON));

または、オブジェクトを文字列に変換して JSON パーサーに渡すのではなく、デシリアライズ後にオブジェクトを消費するだけで、さらに頭痛の種になります

Mouser も述べたように、プロジェクトにsystem.web.extensions.dllを含めることで利用できるSystem.Web.Script.Serializationを使用する必要があり、そのためにはプロジェクト プロパティのターゲット フレームワークを に変更する必要があります。.NET Framework 4

編集

デシリアライズされたオブジェクトを消費するためのトリックが使用されていますdynamic

JavaScriptSerializer js = new JavaScriptSerializer();
dynamic obj = js.DeserializeObject(AlienJSON);

質問のJSONの場合は、単に使用します

string body = obj["body"];

または、JSON が配列の場合

if (obj is Array) {
    foreach(dynamic o in obj){
        string body = obj[0]["body"];
        // ... do something with it
    }
}
于 2015-02-07T16:32:23.573 に答える