FundingCircle / jackdaw

A Clojure library for the Apache Kafka distributed streaming platform.
https://fundingcircle.github.io/jackdaw/
BSD 3-Clause "New" or "Revised" License
368 stars 80 forks source link

Avro schemas with union types with int declared before float encode all floats to ints #349

Open kevinmershon opened 1 year ago

kevinmershon commented 1 year ago

We have a schema which is admittedly wonky and there's a field with the union type declared in this order:

{
  "doc": "Single simple value.",
  "name": "value",
  "type": ["null", "boolean", "int", "long", "float", "double", "string"]
}

Because the union types are tried in-order, the num-coercable? function used for type-guarding ints and longs runs first, causing all our floats/doubles to cast to integers when serializing to avro.

Replacing the implementation with the following, fixes it:

(defn int-coercable?
  "Checks whether `x` can be coerced to a integer with `coercion-fn`
  (such as `long`)."
  [x coercion-fn]
  (try
    (and (integer? x)
         (coercion-fn (bigint x)))
    (catch RuntimeException _e
      false)))
(def ^:deprecated num-coercable? int-coercable?