Paradigm Shift Design

ISHITOYA Kentaro's blog.

Json.NETでSelf referencing loopと言われるときの対処法

ん、ちょっとはまったので、メモ。

Json.NETでオブジェクトをSerializeするときに、オブジェクトがCompositeパターンな感じだと、「同じクラスがネストしていますよ、間違いじゃないですか?」とJsonSerializationExceptionを出して、ご丁寧に教えてくれる。

'Newtonsoft.Json.JsonSerializationException' の初回例外が Newtonsoft.Json.dll で発生しました。
Newtonsoft.Json.JsonSerializationException: Self referencing loop

で、このお節介を、余計だ!と言い張るためには、Serializeする前に設定する必要がある。僕は、君に注意されるほどおっちょこちょいじゃない!

/**
 * creates a json request string
 * @param method String method to call
 * @param param ArrayList of arguments
 * @return String request string for jsonic
 */
protected String createJSONRequest(String method, ArrayList param)
{
    return "{\"method\":\"" + method + "\"," +
           " \"params\":" + JavaScriptConvert.SerializeObject(param) + "," +
           " \"id\":1}";
}

を、

/**
 * creates a json request string
 * @param method String method to call
 * @param param ArrayList of arguments
 * @return String request string for jsonic
 */
protected String createJSONRequest(String method, ArrayList param)
{
    return "{\"method\":\"" + method + "\"," +
           " \"params\":" + this.serializeObjectToJSON(param as Object) + "," +
           " \"id\":1}";
}

/**
 * serializeObjectToJSON
 */
protected String serializeObjectToJSON(Object value)
{
    Type type = value.GetType();

    Newtonsoft.Json.JsonSerializer json = new Newtonsoft.Json.JsonSerializer();

    json.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

    StringWriter sw = new StringWriter();
    JsonWriter writer = new JsonWriter(sw);
    writer.Formatting = Formatting.None;

    writer.QuoteChar = '"';
    json.Serialize(writer, value);

    string output = sw.ToString();
    writer.Close();
    sw.Close();

    return output;
}

のように書き直す必要がある。
JavaScriptConvertは便利なクラスだけど、まったくカスタマイズ性がないので、
DataTable JSON Serialization in JSON.NET and JavaScriptSerializer - Rick Strahl's Web Log
を参考にJsonSerializerを使ってSerializeしてくれる関数を書かないといけない。


で、動かしてみるに、キチンとSerializeされました。
…でも、きっといつか、おせっかいが重要だったことに気がつくんだよね。世の常だ。


ちなみに、Json.NETは3.0が8月24日にリリースされていました。

ご確認を。


ところで、「kids」を「ガキ」と訳す山形さん*1のCODEは今12章。あと7章!
先は長い…

*1:別に、kidsをガキと訳すことに何かいいたいのではなくて、一応学術系の本に出てくる「kids-mode browsing」という語の訳がガキモードブラウジングなことに何かいいたいのだ