# Saving complex numbers using JSON3

**URL:** <https://discourse.julialang.org/t/saving-complex-numbers-using-json3/83452>\
**Category:** Data\
**Tags:** json, python, json3, complex-numbers\
**Created:** [June 28, 2022, 11:06am UTC](https://discourse.julialang.org/t/saving-complex-numbers-using-json3/83452 "2022-06-28T11:06:43Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jlbosse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlbosse/32/11274_2.png) [@jlbosse](https://discourse.julialang.org/u/jlbosse)\
**Post date:** [June 28, 2022, 11:06am UTC](https://discourse.julialang.org/t/saving-complex-numbers-using-json3/83452/1 "2022-06-28T11:06:43Z")

</div>

I am trying to save Complex numbers in json files formatted in a python compatible way as

```julia
using JSON3
c = 1+5im
d = Dict("c" => c)
jsonstring = JSON3.pretty(d)
#= should be
{
    "c" : 1+5j
}
=#

```

This is how far I got, using the [documentation](https://quinnj.github.io/JSON3.jl/stable/#JSON3.RawType)

```julia
using JSON3
using StructTypes

StructTypes.StructType(::Type{Complex{RT}}) where {RT<:Real} = JSON3.RawType() 

function StructTypes.construct(
         ::Type{Complex{RT}}, x::JSON3.RawValue) where {RT<:Real}
    return parse(Complex{RT}, unsafe_string(pointer(x.bytes, x.pos), x.len))
end

function JSON3.rawbytes(x::Complex{RT}) where {RT<:Real}
    str = x.im > zero(RT) ? "$(x.re)+$(x.im)j" : "$(x.re)$(x.im)j"
    return transcode(UInt8, str)
end

c = 1+5im
d = Dict("c" => c)

JSON3.write(d)
# works fine and returns "{\"c\":1+5j}"

JSON3.read(JSON3.write(c), Complex{Int})
# works fine and returns the original number

JSON3.pretty(d)
#= crashes with
ERROR: ArgumentError: invalid JSON at byte position 7 while parsing type JSON3.Object:
ExpectedComma {"a":1+7j}
=#

```

Is it possible to create such a JSON serialisation of complex numbers using JSON3? And if yes, what am I missing to make JSON3.pretty work here?

I think this also relates to the more general question: If I define a serialisation via `rawbytes` for a type, how do I tell `JSON3` to use the correct deserialisation routine? It seems that the error I am getting stems from the unexpected “+” sign in the json string.

---

<div class="post-metadata">

**Author:** ![helgee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/helgee/32/2022_2.png) [@helgee](https://discourse.julialang.org/u/helgee)\
**Post date:** [June 28, 2022, 12:44pm UTC](https://discourse.julialang.org/t/saving-complex-numbers-using-json3/83452/2 "2022-06-28T12:44:55Z")

</div>

What are you using on the Python side that expects this format? The problem seems to be that it is not valid JSON according to [the spec](https://json.org).

---

<div class="post-metadata">

**Author:** ![jlbosse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlbosse/32/11274_2.png) [@jlbosse](https://discourse.julialang.org/u/jlbosse)\
**Post date:** [June 28, 2022, 12:54pm UTC](https://discourse.julialang.org/t/saving-complex-numbers-using-json3/83452/3 "2022-06-28T12:54:15Z")

</div>

So far the python side does not exist yet, but the idea was to write our own decoder that is happy with this format. But given that this is not valid json it might be better to do `{"c": "1+5j"}` instead, i.e. serialise complex numbers as their string representation.

Nevertheless, if what I originally wanted is possible

---

<div class="post-metadata">

**Author:** ![quinnj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/quinnj/32/11_2.png) [@quinnj](https://discourse.julialang.org/u/quinnj)\
**Post date:** [June 28, 2022, 4:24pm UTC](https://discourse.julialang.org/t/saving-complex-numbers-using-json3/83452/4 "2022-06-28T16:24:20Z")

</div>

Ah, this is because `JSON3.pretty` ends up calling `JSON3.read` while printing. I can’t remember the exact details since @fedorc recently reworked that code. It seems like we could give you the ability to pass in a type name or something and still have this work.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [June 28, 2022, 6:48pm UTC](https://discourse.julialang.org/t/saving-complex-numbers-using-json3/83452/5 "2022-06-28T18:48:19Z")

</div>

Rust’s Serde has 3 different ways of serializing a type name: internally, externally, and adjacently tagged.

[https://serde.rs/enum-representations.html](https://serde.rs/enum-representations.html)

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [June 28, 2022, 7:06pm UTC](https://discourse.julialang.org/t/saving-complex-numbers-using-json3/83452/6 "2022-06-28T19:06:11Z")

</div>

JSON allows objects, so on the Julia side you can define a suitable struct and write it into JSON, like this:

```julia
using JSON3, StructTypes

struct JCX
    real::Float64
    imaginary::Float64
end
JCX(x) = JCX(reim(x)...)

StructTypes.StructType(::Type{JCX}) = StructTypes.Struct()

c = 2.72+3.14im

j = JSON3.write(JCX(c))
# {"real":2.72,"imaginary":3.14}
c1 = JSON3.read(j, JCX)
# JCX(2.72, 3.14)

```
