# Allow EpochConverter to receive null json value

**URL:** <https://forum.crystal-lang.org/t/allow-epochconverter-to-receive-null-json-value/2273>\
**Category:** Help & Support\
**Created:** [June 23, 2020, 3:42pm UTC](https://forum.crystal-lang.org/t/allow-epochconverter-to-receive-null-json-value/2273 "2020-06-23T15:42:47Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![curious2learn](https://avatars.discourse-cdn.com/v4/letter/c/5daacb/32.png) [@curious2learn](https://forum.crystal-lang.org/u/curious2learn)\
**Post date:** [June 23, 2020, 3:42pm UTC](https://forum.crystal-lang.org/t/allow-epochconverter-to-receive-null-json-value/2273/1 "2020-06-23T15:42:47Z")

</div>

First, sorry that I am still on Crystal v0.30, and still using JSON.mapping. But likely the issue I am having does not have to do with this.

I have field called `timecreated` in the JSON that I send to server. The JSON.mapping code is

```
JSON.mapping(
     timecreated: {type: Time?, converter: Time::EpochConverter}
)

```

If I pass a JSON value in my postdata where timecreated field is `null` then I get an error saying `Expected Int but was Null`. This is despite declaring the field as `nilable`. I thought, this perhaps has to do with `Time::EpochConverter` not being able to handle `null` JSON value. (If I pass an integer for timecreated, I don’t get any error). So, I tried to extend `Time::EpochConverter` to allow for `null` values by adding the following code to my `src` file.

```
module Time::EpochConverter
    def self.from_json(value : JSON::PullParser) : Time|Nil
        if (value.read_int_or_null)
            Time.unix(value.read_int)
        else
            nil
        end
    end
end

```

With this code added, `null` no longer throws an error. However, if I pass an `integer` JSON value to the `timecreated` field, I get the following error:  
`Expected Int but was String`

I have two questions: (1) Why is it throwing this `Expected Int but was String`  
error because of the code I added?  
(2) How do I allow EpochConverter to accept `null` json values.

Thank you.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [June 23, 2020, 4:23pm UTC](https://forum.crystal-lang.org/t/allow-epochconverter-to-receive-null-json-value/2273/2 "2020-06-23T16:23:19Z")

</div>

Given `JSON.mapping` is deprecated, I would just change your implementation to use `JSON::Serializable`, which doesn’t seem to have this problem: [https://play.crystal-lang.org/#/r/9bb0](https://play.crystal-lang.org/#/r/9bb0).

While on the other-hand, using `JSON.mapping`, you run into this problem: [https://play.crystal-lang.org/#/r/9bb2](https://play.crystal-lang.org/#/r/9bb2).

---

<div class="post-metadata">

**Author:** ![curious2learn](https://avatars.discourse-cdn.com/v4/letter/c/5daacb/32.png) [@curious2learn](https://forum.crystal-lang.org/u/curious2learn)\
**Post date:** [June 23, 2020, 6:02pm UTC](https://forum.crystal-lang.org/t/allow-epochconverter-to-receive-null-json-value/2273/3 "2020-06-23T18:02:15Z")

</div>

Thank you @Blacksmoke16. I will convert it to JSON::Serializable and try with that.

---

<div class="post-metadata">

**Author:** ![bcardiff](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bcardiff/32/3_2.png) [@bcardiff](https://forum.crystal-lang.org/u/bcardiff)\
**Post date:** [June 23, 2020, 6:46pm UTC](https://forum.crystal-lang.org/t/allow-epochconverter-to-receive-null-json-value/2273/4 "2020-06-23T18:46:56Z")

</div>

The following should work:

```auto
require "json"

class MyObject
  JSON.mapping(
    created_at: {type: Time?, converter: Time::EpochConverter, nilable: true}
  )
end

pp MyObject.from_json %({"created_at":null})
pp MyObject.from_json %({"created_at":1592929230})

```

It seems that the logic to wrap the pull\_parser with a `read_null_or` is not handled when the type is nilable but there is no nilable explicit named argument.

---

<div class="post-metadata">

**Author:** ![bcardiff](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/bcardiff/32/3_2.png) [@bcardiff](https://forum.crystal-lang.org/u/bcardiff)\
**Post date:** [June 23, 2020, 6:50pm UTC](https://forum.crystal-lang.org/t/allow-epochconverter-to-receive-null-json-value/2273/5 "2020-06-23T18:50:41Z")

</div>

And just because it’s fun, this would be another alternative

```auto
class MyObject
  JSON.mapping(
    created_at: {type: Time?, converter: NilableConverter(Time::EpochConverter)}
  )
end

module NilableConverter(T)
  def self.from_json(value : JSON::PullParser)
    value.read_null_or do
      T.from_json(value)
    end
  end
end

```

---

<div class="post-metadata">

**Author:** ![curious2learn](https://avatars.discourse-cdn.com/v4/letter/c/5daacb/32.png) [@curious2learn](https://forum.crystal-lang.org/u/curious2learn)\
**Post date:** [June 23, 2020, 7:56pm UTC](https://forum.crystal-lang.org/t/allow-epochconverter-to-receive-null-json-value/2273/6 "2020-06-23T19:56:46Z")

</div>

Thank you @bcardiff. I will try this. I tried using JSON::Serializable. Specifically, using

```
@[JSON::Field(emit_null: true, converter: Time::EpochConverter)]
property timecreated : Time?

```

But with that I get the error:

```
Expected String but was Int

```

I don’t know why it is expecting a String. Could be because I am using an older version of Crystal. But let me try your solution. Thank you.

---

<div class="post-metadata">

**Author:** ![curious2learn](https://avatars.discourse-cdn.com/v4/letter/c/5daacb/32.png) [@curious2learn](https://forum.crystal-lang.org/u/curious2learn)\
**Post date:** [June 23, 2020, 8:00pm UTC](https://forum.crystal-lang.org/t/allow-epochconverter-to-receive-null-json-value/2273/8 "2020-06-23T20:00:35Z")

</div>

> [@bcardiff](#):
>
> ```auto
> class MyObject
> JSON.mapping(
> created_at: {type: Time?, converter: Time::EpochConverter, nilable: true}
> )
> end
> 
> ```

The above solution worked great. Thank you!
