0
votes

This seems to be a very easy problem to solve but apparently I haven't been able to think straight or look at the right place.

Say I have a schema, where columns are named in snake_case, by convention, e.g. branch_id.

Normally, if the data is coming from a Phoenix form, you'd have the keys of the data corresponding exactly to the keys of the schema, so that you can write %MyStruct{} |> cast(attrs, [:branch_id]) etc.

However, in my JSON API, the incoming JSON object would have keys in camelCase, e.g. "branchId".

Is there any function from Ecto.Changeset that I can use to conveniently correspond such keys from the incoming data to the columns in my schema?

An obvious solution would be to (in the controller,) Enum.map over the incoming JSON first, use Macro.underscore to convert the keys, and collect the result back into a map, before passing it to the changeset function. However that would seem to be really extraneous and inefficient.

This is not only limited to the situation of snake_case vs. camelCase, but potentially any situation where the key looks different from the intended column name.

1

1 Answers

1
votes

If you are writing the client sending the JSON to your API, require that your API call JSON keys are snake_case to match the API endpoint.

The Macro.camelize and Macro.underscore functions are also not suitable for certain cases since they do not support unicode or invalid-in-Elixir-identifier characters, so you may want to look into Case2 if you want to accept camelCase and mutate into snake_case.

You could implement recase conditionally, e.g. if you receive a request with camelCase keys, Enum.map or Enum.filter and recase, but in most cases it is best to just spec your client API calls to match your backend API endpoints

Edit: changed Recase ref to Case2 since Recase apparently can't handle unicode either :P