Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Array encode error if optional key is not presented #90

Open
JessicaHsu opened this issue Jul 26, 2023 · 2 comments
Open

Array encode error if optional key is not presented #90

JessicaHsu opened this issue Jul 26, 2023 · 2 comments

Comments

@JessicaHsu
Copy link

I need to put a record into a array as an optional item.
It seems the optional key must be presented in this case.
Is this an expected behavior?

Elixir 1.8
OTP 22
:avro_ex 2.1

Schema

profile_schema = %{
    "type" => "record",
    "name" => "profile",
    "fields" => [
      %{"name" => "name", "type" => "string"},
      %{"name" => "age", "type" => ["null", "int"]},            
    ]
}

array_schmea = %{
      "type" => "array",
      "items" => [
        "null",
        "string",
        profile_schema
      ]
}

final_schema = AvroEx.decode_schema!(array_schmea, strict: true)

Usage

NG

profile = %{
  name: "Alice"
}

example = ["1","2", profile]

example_bin = AvroEx.encode!(final_schema, example) |> IO.inspect(label: "encode")
AvroEx.decode!(final_schema, example_bin) |> IO.inspect(label: "decode")

** (AvroEx.EncodeError) Schema Mismatch: Expected value of Union<possibilities=null|string|Record<name=profile>>, got %{name: "Alice"}
    (avro_ex 2.1.0) lib/avro_ex.ex:163: AvroEx.encode!/3
    #cell:k6mfb4za2ebwu6sux5ix32zdwrvnacar:27: (file)

OK

profile = %{
  name: "Alice",
  age: nil
}

example = ["1","2", profile]

example_bin = AvroEx.encode!(final_schema, example) |> IO.inspect(label: "encode")
AvroEx.decode!(final_schema, example_bin) |> IO.inspect(label: "decode")

@davydog187
Copy link
Member

davydog187 commented Aug 3, 2023

Hello thanks for the report! i verified this behavior using the following iex session.

With that being said, this is the intended behavior of the API. nullable fields are not optional, so you can't omit their keys. I believe this behavior is preferable as it ensures that you have the correct data shape.

Can you please explain your usecase?

# Avro EX #90

```elixir
Mix.install([
  {:avro_ex, "~> 2.1"}
])

Schema

profile_schema = %{
  "type" => "record",
  "name" => "profile",
  "fields" => [
    %{"name" => "name", "type" => "string"},
    %{"name" => "age", "type" => ["null", "int"]}
  ]
}

array_schmea = %{
  "type" => "array",
  "items" => [
    "null",
    "string",
    profile_schema
  ]
}

final_schema = AvroEx.decode_schema!(array_schmea, strict: true)

NG

profile = %{
  name: "Alice"
}

example = ["1", "2", profile]

example_bin = AvroEx.encode!(final_schema, example) |> IO.inspect(label: "encode")
AvroEx.decode!(final_schema, example_bin) |> IO.inspect(label: "decode")

OK

profile = %{
  name: "Alice",
  age: nil
}

example = ["1", "2", profile]

example_bin = AvroEx.encode!(final_schema, example) |> IO.inspect(label: "encode")
AvroEx.decode!(final_schema, example_bin) |> IO.inspect(label: "decode")

@JessicaHsu
Copy link
Author

JessicaHsu commented Aug 4, 2023

Hi thanks for the reply!

Actually, my data structure have some optional fields, and I thought "type" => ["null", "int"] would do the trick.
Since nullable fields are not optional, do you know how to define my profile_schema to make the age be an optional key so that I can encode the profile and omit the age? Also, I need the profile to be one of my array item, which means the array_schmea would contains profile in the end.

My use case:
I have an array which takes a payload. The payload could be different data structure which have several optional fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants