4

I'm using json-io for converting some JSON data to Java objects:

DataTransferContainer dataTransferContainer = (DataTransferContainer)JsonReader.jsonToJava(json);

DataTransferContainer is just an object containing some GeoJson elements. It does not matter for this issue.

The above code works in JUnit test outside Android, but when I run this on Android, I get this RuntimeException:

12-07 20:12:51.260: E/AndroidRuntime(2002): FATAL EXCEPTION: AsyncTask #1
12-07 20:12:51.260: E/AndroidRuntime(2002): java.lang.RuntimeException: An error occured while executing doInBackground()
12-07 20:12:51.260: E/AndroidRuntime(2002):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.lang.Thread.run(Thread.java:1019)
12-07 20:12:51.260: E/AndroidRuntime(2002): Caused by: java.lang.ExceptionInInitializerError
12-07 20:12:51.260: E/AndroidRuntime(2002):     at com.mydomain.myapp.dataprocessing.JsonConverter.jsonObjectToObject(JsonConverter.java:22)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at com.mydomain.myapp.dataprocessing.DataManagerTask.processDataFromRemote(DataManagerTask.java:104)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at com.mydomain.myapp.dataprocessing.DataManagerTask.doInBackground(DataManagerTask.java:56)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at com.mydomain.myapp.dataprocessing.DataManagerTask.doInBackground(DataManagerTask.java:18)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
12-07 20:12:51.260: E/AndroidRuntime(2002):     ... 4 more
12-07 20:12:51.260: E/AndroidRuntime(2002): Caused by: java.util.regex.PatternSyntaxException: Syntax error U_ILLEGAL_ARGUMENT_ERROR
12-07 20:12:51.260: E/AndroidRuntime(2002): (\d{2})[:.](\d{2})[:.](\d{2})[.](\d{1,10})([+-]\d{2}[:]?\d{2}|Z)?
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.regex.Pattern.compileImpl(Native Method)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.regex.Pattern.compile(Pattern.java:400)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.regex.Pattern.<init>(Pattern.java:383)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at java.util.regex.Pattern.compile(Pattern.java:374)
12-07 20:12:51.260: E/AndroidRuntime(2002):     at com.cedarsoftware.util.io.JsonReader.<clinit>(JsonReader.java:114)
12-07 20:12:51.260: E/AndroidRuntime(2002):     ... 10 more

In JsonReader, line 114 looks like this:

private static final Pattern timePattern1 = Pattern.compile("(\\d{2})[:.](\\d{2})[:.](\\d{2})[.](\\d{1,10})([+-]\\d{2}[:]?\\d{2}|Z)?");

I was able to narrow it down. It's this part: [:.]

It just means "any character" or "colon". What's wrong with that on Android?

Bevor
  • 8,396
  • 15
  • 77
  • 141
  • I can confirm the problem. – Stan Dec 15 '14 at 22:48
  • 2
    BTW, changing the order solves the problem, that is `[.:]` is accepted and seems working as expected. I have no idea why it does not work other way round in Android. Also please note that `.` means exactly "dot" here, not any character, because it is inside character class. – Stan Dec 15 '14 at 23:17
  • Thanks for the hint. Meanwhile I rewrote the library for my purposes and I will use for Android my own version of it. – Bevor Dec 20 '14 at 11:20
  • I will make this change (rearrange to have [.:]) within the actual sources of json-io. Btw, the project is maintained at: https://github.com/jdereg/json-io . I have been updating the comments on google.code, but at this point GitHub is the true host for json-io. – John DeRegnaucourt Jan 27 '15 at 23:32
  • @Stan: This answer (changing `[:.]` to `[.:]`) fixed it for me in another Java question. Good catch! I wonder if it has anything to do with the fact that POSIX supports `[:digit:]` format, and whether it sees the `[:` and thinks that it is starting a POSIX block. *shrug* – OnlineCop Jan 11 '16 at 18:42
  • I have a similar problem: http://stackoverflow.com/questions/38376190/patternsyntaxexception-using-apache-poi .... any idea? – devnull69 Jul 14 '16 at 13:55
  • @Bevor I am sure the root cause of the bug is that there is a "feature" in the ICU regex library: it recognizes POSIX character classes outsiude bracket expressions (`[:digit:]+` = `[[:digit:]]+`). – Wiktor Stribiżew Feb 12 '18 at 08:03

1 Answers1

1

In ICU regex patterns, bracket expression pattern cannot start with :.

You need to change the pattern to

Pattern.compile("(\\d{2})[.:](\\d{2})[.:](\\d{2})[.](\\d{1,10})([+-]\\d{2}:?\\d{2}|Z)?")

Note the changes:

  • [:] is changed to :
  • [:.] is changed to [.:]

The regex library used in Android is ICU, and one of its peculiarities is that it supports POSIX character classes outside bracket expressions. That means you may write [[:digit:]] to match a digit, or [:digit:] (which is invalid in most other regex flavors including POSIX). The ICU regex parser seems to have problems parsing bracket expressions starting with : and surely it is a bug.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563