Hi all,

Kafka currently use scala.util.parsing.json.JSON as its json parser and it
has a number of issues:

* It encourages unsafe casts (returns `Option[Any]`)
* It's slow (it relies on parser combinators under the hood)
* It's not thread-safe (so external locks are needed to use it in a
concurrent environment)
* It's deprecated (it should have never been included in the standard
library in the first place)

KAFKA-1595[1] has been filed to track this issue.

I initially proposed a change using spray-json's AST with the jawn
parser[2]. Gwen expressed some reservations about the choice (a previous
discussion had concluded that Jackson should be used instead) and asked me
to raise the issue in the mailing list[3].

In order to have a fair comparison, I implemented the change using Jackson
as well[4]. I paste part of the commit message:

"A thin wrapper over Jackson's Tree Model API is used as the replacement.
This wrapper
increases safety while providing a simple, but powerful API through the
usage of the
`DecodeJson` type class. Even though this has a maintenance cost, it makes
the API
much more convenient from Scala. A number of tests were added to verify the
behaviour of this wrapper. The Scala module for Jackson doesn't provide any
help for our current usage, so we don't
depend on it."

A comparison between the two approaches as I see it:

Similarities:

   1. The code for users of the JSON library is similar
   2. No third-party dependencies
   3. Good performance

In favour of using Jackson:

   1. Same library for client and broker
   2. Widely used

In favour of using spray-json and jawn:

   1. Simple type class based API is included and it has a number of nice
   features:
      1. Support for parsing into case classes (we don't use this yet, but
      we could use it to make the code safer and more readable in some
cases)[5].
      2. Very little reflection used (only for retrieving case classes
      field names).
      3. Write support (could replace our `Json.encode` method).
   2. Less code to maintain (ie we don't need a wrapper to make it nice to
   use from Scala)
   3. No memory overhead from wrapping the Jackson classes (probably not a
   big deal)

I am happy to go either way as both approaches have been implemented and I
am torn between the options.

What do you think?

Best,
Ismael

[1] https://issues.apache.org/jira/browse/KAFKA-1595
[2]
https://github.com/ijuma/kafka/commit/80974afefc00eb6313a7357e7942d5d86ffce84d
[3]
https://issues.apache.org/jira/browse/KAFKA-1595?focusedCommentId=14512881&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-14512881
[4]
https://github.com/ijuma/kafka/commit/4ca0f1111eb37e8be2d388b60efacc19bc6788b6
[5] The Scala module for Jackson (which is not being used in the commit
above) also supports this, but it uses a reflection-based approach instead
of type classes.

Reply via email to