{"action":"created","issue":{"url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1948","repository_url":"https://api.github.com/repos/FasterXML/jackson-databind","labels_url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1948/labels{/name}","comments_url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1948/comments","events_url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1948/events","html_url":"https://github.com/FasterXML/jackson-databind/issues/1948","id":300997596,"number":1948,"title":"Locale deserialize 'zh-hant_CN'","user":{"login":"takeseem","id":4768523,"avatar_url":"https://avatars3.githubusercontent.com/u/4768523?v=4","gravatar_id":"","url":"https://api.github.com/users/takeseem","html_url":"https://github.com/takeseem","followers_url":"https://api.github.com/users/takeseem/followers","following_url":"https://api.github.com/users/takeseem/following{/other_user}","gists_url":"https://api.github.com/users/takeseem/gists{/gist_id}","starred_url":"https://api.github.com/users/takeseem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/takeseem/subscriptions","organizations_url":"https://api.github.com/users/takeseem/orgs","repos_url":"https://api.github.com/users/takeseem/repos","events_url":"https://api.github.com/users/takeseem/events{/privacy}","received_events_url":"https://api.github.com/users/takeseem/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2018-02-28T11:59:15Z","updated_at":"2018-03-01T03:53:58Z","closed_at":null,"author_association":"NONE","body":"`zh-hant_CN` will convert to `zh_HANT_cn`\r\nLocale include (language, country, variant), Locale.toString() use '\\_' to split then `{language}_{country}_({variant}_# | #){script}-{extensions}`\r\n\r\nbut Jackson deserialize Locale use '-' or '\\_'  : (\r\ncode: [FromStringDeserializer.Std._deserialize](https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java#L274)\r\n\r\n[iana language-tags](https://www.iana.org/assignments/language-tags/language-tags.xml#Mark_Davis)\r\n```\r\nzh-Hant\tChinese, in traditional script\t[Mark_Davis][Mark_Davis_2]\t\r\nzh-Hant-CN\tPRC Mainland Chinese in traditional script\t[Mark_Davis][Mark_Davis_2]\t\r\nzh-Hant-HK\tHong Kong Chinese in traditional script\t[Mark_Davis][Mark_Davis_2]\t\r\nzh-Hant-MO\tMacao Chinese in traditional script\t[Mark_Davis][Mark_Davis_2]\t\r\nzh-Hant-SG\tSingapore Chinese in traditional script\t[Mark_Davis][Mark_Davis_2]\t\r\nzh-Hant-TW\tTaiwan Chinese in traditional script\t[Mark_Davis][Mark_Davis_2]\r\n```\r\n\r\n[rfc4647 language lookup](https://tools.ietf.org/html/rfc4647#section-3.4)\r\n```\r\n  Example of a Lookup Fallback Pattern\r\n\r\n   Range to match: zh-Hant-CN-x-private1-private2\r\n   1. zh-Hant-CN-x-private1-private2\r\n   2. zh-Hant-CN-x-private1\r\n   3. zh-Hant-CN\r\n   4. zh-Hant\r\n   5. zh\r\n   6. (default)\r\n```\r\n\r\n```java\r\n\tpublic static void main(String[] args) {\r\n\t\tSystem.out.println(new Locale(\"zh-hant\", \"CN\"));\r\n\t}\r\n```\r\nin jdk1.5 -> 1.8\r\n```\r\njdk1.5\tzh-hant_CN\r\njdk1.6\tzh-hant_CN\r\njdk1.7\tzh-hant_CN\r\njdk1.8\tzh-hant_CN\r\n```\r\n\r\nothers: \r\n#1344 \r\n#1600 "},"comment":{"url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/comments/369466358","html_url":"https://github.com/FasterXML/jackson-databind/issues/1948#issuecomment-369466358","issue_url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1948","id":369466358,"user":{"login":"takeseem","id":4768523,"avatar_url":"https://avatars3.githubusercontent.com/u/4768523?v=4","gravatar_id":"","url":"https://api.github.com/users/takeseem","html_url":"https://github.com/takeseem","followers_url":"https://api.github.com/users/takeseem/followers","following_url":"https://api.github.com/users/takeseem/following{/other_user}","gists_url":"https://api.github.com/users/takeseem/gists{/gist_id}","starred_url":"https://api.github.com/users/takeseem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/takeseem/subscriptions","organizations_url":"https://api.github.com/users/takeseem/orgs","repos_url":"https://api.github.com/users/takeseem/repos","events_url":"https://api.github.com/users/takeseem/events{/privacy}","received_events_url":"https://api.github.com/users/takeseem/received_events","type":"User","site_admin":false},"created_at":"2018-03-01T03:53:57Z","updated_at":"2018-03-01T03:53:57Z","author_association":"NONE","body":"* In jackson use `Locale.toString()` to serialize Locale: [`sers.put(Locale.class, new ToStringSerializer(Locale.class));`](https://github.com/FasterXML/jackson-databind/blob/2.9/src/main/java/com/fasterxml/jackson/databind/ser/std/StdJdkSerializers.java#L36)\r\n* In java `Locale.toString()`, it's use '\\_' to split the Language, Country, Variant.\r\n* If Locale is 'zh-hant' or ''zh-hant_CN', use jackson deserialize result: language=zh, country=HANT, but the right is language=zh-hant.\r\n\r\n\r\n* [jackson v2.7.6](https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.7.6/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java#L231) is right\r\n```java\r\n            case STD_LOCALE:\r\n                {\r\n                    int ix = value.indexOf('_');\r\n                    if (ix < 0) { // single argument\r\n                        return new Locale(value);\r\n                    }\r\n                    String first = value.substring(0, ix);\r\n                    value = value.substring(ix+1);\r\n                    ix = value.indexOf('_');\r\n                    if (ix < 0) { // two pieces\r\n                        return new Locale(first, value);\r\n                    }\r\n                    String second = value.substring(0, ix);\r\n                    return new Locale(first, second, value.substring(ix+1));\r\n                }\r\n```\r\n* [jackson v2.7.7](https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.7.7/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java#L231) #1344[Deserializing locale assumes JDK separator underscore, does not accept RFC specified hyphen]  (https://github.com/FasterXML/jackson-databind/commit/07b6d6636670b2a9f14ac265186790db11cfd52d?diff=split#diff-cb072a60c804dd335a8f4988bac7ce48R231)\r\n```java\r\n            case STD_LOCALE:\r\n                {\r\n                    int ix = _firstHyphenOrUnderscore(value);\r\n                    if (ix < 0) { // single argument\r\n                        return new Locale(value);\r\n                    }\r\n                    String first = value.substring(0, ix);\r\n                    value = value.substring(ix+1);\r\n                    ix = _firstHyphenOrUnderscore(value);\r\n                    if (ix < 0) { // two pieces\r\n                        return new Locale(first, value);\r\n                    }\r\n                    String second = value.substring(0, ix);\r\n                    return new Locale(first, second, value.substring(ix+1));\r\n                }\r\n\r\n        protected int _firstHyphenOrUnderscore(String str)\r\n        {\r\n            for (int i = 0, end = str.length(); i < end; ++i) {\r\n                char c = str.charAt(i);\r\n                if (c == '_' || c == '-') {\r\n                    return i;\r\n                }\r\n            }\r\n            return -1;\r\n        }\r\n```\r\nJackson serialize `Locale` default use `Locale.toString()`, It will be broken.\r\n\r\na most of system use the _ to split language, country, variant, like\r\n* en_US\r\n* zh_CN\r\n* zh_TW\r\n* zh-hant_CN\r\n"}}
{"actor":{"display_login":"takeseem"}}