{ "name": "name", "id": 12112, "sex": "male", "birthday": "2012-09-08" }
转换成
{ “name” => "name", "id" => 12112, "sex" =>"male", "birthday" => "2012-09-08" }
有没有 gem,或者方法?
[1] pry(main)> require'json'
=> true
[2] pry(main)> JSON.parse("{\"val\":\"test\",\"val1\":\"test1\",\"val2\":\"test2\"}")
=> {"val"=>"test", "val1"=>"test1", "val2"=>"test2"}
[3] pry(main)> '''
[3] pry(main)* {
[3] pry(main)* "name": "name",
[3] pry(main)* "id": 12112,
[3] pry(main)* "sex": "male",
[3] pry(main)* "birthday": "2012-09-08"
[3] pry(main)* }
[3] pry(main)* '''
=> "\n{\n\"name\": \"name\",\n\"id\": 12112,\n\"sex\": \"male\",\n\"birthday\": \"2012-09-08\"\n}\n"
[4] pry(main)> x = _
=> "\n{\n\"name\": \"name\",\n\"id\": 12112,\n\"sex\": \"male\",\n\"birthday\": \"2012-09-08\"\n}\n"
[5] pry(main)> JSON.parse(x)
=> {"name"=>"name", "id"=>12112, "sex"=>"male", "birthday"=>"2012-09-08"}
Char 还是有点用的,Ruby 的 String 不是 Enumerable 的,也没有 Char. 所以很多好使的方法都用不了。( Ruby String 没有内部编码。间接导致实现了个 each_byte each_char. each_char 出来的还都是 String, 这才是略坑爹的地方。
Clojure:
user=> (seq "abc")
(\a \b \c)
user=> (first "abc")
\a
user=> (last "abc")
\c
user=> (cycle "abc")
(\a \b \c \a \b \c \a \b \c \a ...)
user=> (take 2 "abc")
(\a \b)
user=> (every? char? "abcdefg")
true
Ruby:
[1] pry(main)> "123"
=> "123"
[2] pry(main)> "123".first
NoMethodError: undefined method `first' for "123":String
from (pry):3:in `__pry__'
[3] pry(main)> "123".last
NoMethodError: undefined method `last' for "123":String
from (pry):4:in `__pry__'
[4] pry(main)> "123".map
NoMethodError: undefined method `map' for "123":String
from (pry):6:in `__pry__'
[5] pry(main)> "123".each
NoMethodError: undefined method `each' for "123":String
from (pry):8:in `__pry__'
[6] pry(main)> "123".each_char
=> #<Enumerator: ...>
[7] pry(main)> "123".each_char{|c| p c.class}
String
String
String
=> "123"
如果 Ruby 有 Char, 直接 Mixin Enumerable 就好了。该有的都有了..
#1 楼 @Saito
pry(main)> '''
[3] pry(main)* {
[3] pry(main)* "name": "name",
[3] pry(main)* "id": 12112,
[3] pry(main)* "sex": "male",
[3] pry(main)* "birthday": "2012-09-08"
[3] pry(main)* }
[3] pry(main)* '''
怎么得到下面的结果呢?
"\n{\n\"name\": \"name\",\n\"id\": 12112,\n\"sex\": \"male\",\n\"birthday\": \"2012-09-08\"\n}\n"
我怎么都不好使呢?
char 类型问题可多了... 首先字符串必须内码一致并且用定长编码,如果处理是不同编码的内容,就要先统一转换成内码再处理,你是可以直接用 enumerable 方法,但是之前和之后的转换比 each_char / each_byte 要麻烦,而且用户又怎么知道迭代的是字符还是字节呢?
内码其实用 utf-32 才是正确的,但由于历史原因 (最初他们以为全宇宙字符不会超过 65535 个), 常见语言都用了 utf-16 (最初定长的时候叫 ucs-2), 例如 C++ 的 wchar_t
(wchar_t
在各平台长度不一样又是另一个坑了...), OC 的 uchar
, Java 的 char
.
但 utf-16 和 utf-32 都有 less endian 和 big endian 的不同 (例如 windows 的 "unicode" 和 java 的 "unicode" 是二进制不兼容的)...
超过 65535 的字符要两个 char 才能表示,为了解决这个问题,就衍生出各种新概念 (如 glyph) 去表达原本"字符"的意思,定长编码的预设也失效了,char 类型也不是字符的意思了,可坑爹了...
ruby 处理 utf-8 字符串:
"𝄞".size #=> 1
"𝄞".bytesize #=> 4
java 里:
String s = "𝄞";
s.length(); //=> 2 WTF?
s.codePointCount(0, s.length()); //=> 要得到正确的结果, 还要在 javac 加上 -encoding UTF-8 参数
所有基于 java 的二奶语言弄这类超出 65535 的字符都超蛋疼 (jruby 虽然结果正确,但 irb 输入都困难...) clojure 我整了个 rlwrap 可以输入了但正确结果我是弄不出来 ...
归根结底最大的祸害就是这个暧昧不清的 char
类型...
(def wtf "𝄞")
(println (.length wtf))
(println (.codePointCount wtf 0 (.length wtf)))
好吧,跟编码扯上关系就没完了..
内码一致 还是 没有内码 各有各的好处。
(println (seq "123𝄞"))
#=> (1 2 3 ? ?)
这个确实是错的。orz...
统一内码 UTF-8
就没啥问题了。只是性能要下降.. Java 的这个内码选择可能在当时已经是最优的了..
没记错的话,Matz 的书上说:Java 生早了..