Is it possible to create a function to accept only a valid json as parameter/argument ? Not map!
Precisely, I need something that would perform as:
def myFn(obj) when is_json(obj) do
...function content...
end
I am aware that is_json() does not exist in Elixir.
The idea is the function should accept only a string that will parse to json: myFn("{\"k1\":7,"\k2\":"\hello\"}") should be valid but myFn("bla bla bla") not. (the json objects arrive already stringified from an upstream API)
Guard clauses map to VM level instructions, you can only use those specific clauses in guards, in combinations. The only way to know that a string is JSON is to parse it, and I donāt see how you could create a set of guard clauses that would parse JSON.
I understand.
Iāve just discovered that I cannot use a custom function as guard. I initially thought I could create my own is_json guard function ā¦
Too bad Elixir does not have json as a native type. Json is an obliquus format, any modern language must support it natively.
Eg.: I am working with data feeds from industrial machines (automation robots) and their output standard format is json.
I understand your frustration, but I just have to ask the question:
What modern language has native support for JSON?
JavaScript has JSON.parse & JSON.stringify to decode & encode JSON via the std library
Python has json.loads & json.dumps to decode & encode JSON via import json
PHP has json_decode & json_encode to decode & encode JSON via the std library
Ruby has JSON.parse & JSON.generate to decode & encode JSON via require 'json'
ā¦ [1]
The point Iām trying to make is that there doesnāt appear to be a modern language that has ā what I would be willing to call ā native support for JSON.
Every widely used (modern?) language has functions or methods to encode & decode its native objects or data structures to/from JSON.
Even JavaScript (the āJā in JSON) doesnāt appear to have native support.
JSON (JavaScript Object Notation) is a lightweight data-interchange format [1], and in being such, I believe every language would need to attempt to parse JSON order to determine whether itās valid or not, and Elixir is no exception.
JSON is just a format specification of a string, Elixir has native support for strings in any format, including JSON. To the extent that a language can parse a JSON formatted string to a native data structure, and marshal a native data structure to a string of JSON, it has the most āsupport for JSONā possible.
Lamenting that a language doesnāt have āa JSON native typeā is like lamenting that a language doesnāt have āan HTML native typeā.
Validating JSON could be quite slow process depending how big is the string. If Iām not mistaken all guards in Elixir execute in constant time. Meaning variable length JSON string canāt be a guard. Anyway you shouldnāt be validating JSON anywhere else but where the data comes into your system. As JSON being dynamic data, so just checking is JSON might not be enough if you are getting JSON from untrusted source like a browser.
Yes, lists are singly linked lists and must be iterated to the end to find out the length. Thatās why list == [] is recommended over length(list) == 0.
No, the json type is still an internal structure that any JSON string has to be parsed into, thereās no automatic recognition of a string of JSON as JSON, ie. you still need to call: json foo = value:fromJsonString(the_string);.
I dont know if you can do it with a guard but you should be able to do pattern matching in the function clause like
def func(%JSON{} = my_json), do: my_json
That way the function will only match when a JSON struct is passed in.
Edit:
defmodule Test do
defstruct hello: "world", field: 2
def func(%Test{} = my_struct) do
IO.puts("Test struct")
end
end
%Test{hello: "world", field: 2}
|>Test.func()
# Test struct
%{hello: "world", field: 2}
|> Test.func()
# ** (FunctionClauseError) no function clause matching in Test.func/1