Edited at

NSStringからNSJSONSerialization#JSONObjectWithData

More than 3 years have passed since last update.

文字列表記されているJSONをiOS SDK 5から使える NSJSONSerialization#JSONObjectWithData:options:error:NSArray/NSDictionary に変換するとき、ちゃんと書かないとnilになっちゃう。

書くのが楽なのでRubyMotionで説明w


単純な値

error_ptr = Pointer.new(:object)

data = "true".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion:false)
NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves|NSJSONReadingAllowFragments, error: error_ptr)
=> true

単純な値の場合optionsNSJSONReadingAllowFragmentsの指定を含めないとnilになっちゃう。

optionsについてはJSONObjectWithData:options:error: のオプションの意味 -- MD Blogが分かりやすいです。


配列

data = "[1,2,3]".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion:false)

NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves|NSJSONReadingAllowFragments, error: error_ptr)
=> [1, 2, 3]

配列は自然にこれで。


オブジェクト

ちょっとハマりました。

data = "{'a':1, 'b':2}".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion:false)

NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves|NSJSONReadingAllowFragments, error: error_ptr)
=> nil

orz

何がいけないのだろうと、StringからじゃなくNSDictionaryからJSONObjectを生成して文字列に変換すると

data = NSJSONSerialization.dataWithJSONObject({'a'=>1,'b'=>2}, options: 0, error: error_ptr)

NSString.alloc.initWithData(data, encoding:NSUTF8StringEncoding)
=> "{\"a\":1,\"b\":2}"

ダブルクォートで!JSONの仕様ってそうなんですかね?

了解しました。

data = '{"a":1, "b":2}'.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion:false)

NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves|NSJSONReadingAllowFragments, error: error_ptr)
=> {"a"=>1, "b"=>2}

できたヽ(´ー`)ノ


複合

どんとこい!

data = '[1,{"a":1,"b":2},[3,4,[5,6]]]'.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion:false)

json_obj = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves|NSJSONReadingAllowFragments, error: error_ptr)
=> [1, {"a"=>1, "b"=>2}, [3, 4, [5, 6]]]
json_obj[1]
=> {"a"=>1, "b"=>2}
json_obj[2][2]
=> [5, 6]


追記

RubyMotionに慣れてないと、コード見てもなんのこっちゃと思われるかも知れませんね(汗)

RubyMotion(おそらくMacRubyも同じだとおもう)ではNSArrayをRubyのArrayとして、NSDictionaryをRubyのHashとして同じように扱うことができるのですよ!

プログラム内で使用していない変数はREPLから呼べなかったのですがRubyMotion3.5から呼べるようになってました!(\( ⁰⊖⁰)/)