diff --git a/lib/archethic/contracts/interpreter/library/common/json.ex b/lib/archethic/contracts/interpreter/library/common/json.ex index cc800b092..3078b9f39 100644 --- a/lib/archethic/contracts/interpreter/library/common/json.ex +++ b/lib/archethic/contracts/interpreter/library/common/json.ex @@ -20,6 +20,11 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Json do to: Jason, as: :encode! + @spec parse(String.t()) :: any() + defdelegate parse(text), + to: Jason, + as: :decode! + @spec is_valid?(String.t()) :: boolean() def is_valid?(str) do case Jason.decode(str) do @@ -51,5 +56,9 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.Json do AST.is_binary?(first) || AST.is_variable_or_function_call?(first) end + def check_types(:parse, [first]) do + AST.is_binary?(first) || AST.is_variable_or_function_call?(first) + end + def check_types(_, _), do: false end diff --git a/test/archethic/contracts/interpreter/library/common/json_test.exs b/test/archethic/contracts/interpreter/library/common/json_test.exs index 53c9177ce..bf5323488 100644 --- a/test/archethic/contracts/interpreter/library/common/json_test.exs +++ b/test/archethic/contracts/interpreter/library/common/json_test.exs @@ -83,6 +83,122 @@ defmodule Archethic.Contracts.Interpreter.Library.Common.JsonTest do end end + # ---------------------------------------- + describe "parse/1" do + test "should work with string" do + code = ~S""" + actions triggered_by: transaction do + x = Json.parse("{ \"hello\": \"world\", \"foo\": \"bar\"}") + Contract.set_content x.hello + end + """ + + assert %Transaction{data: %TransactionData{content: "world"}} = sanitize_parse_execute(code) + + code = ~S""" + actions triggered_by: transaction do + Contract.set_content Json.parse("\"Whoopi Goldberg\"") + end + """ + + assert %Transaction{data: %TransactionData{content: "Whoopi Goldberg"}} = + sanitize_parse_execute(code) + end + + test "should work with integer" do + code = ~S""" + actions triggered_by: transaction do + x = Json.parse("{ \"integer\": 42, \"foo\": \"bar\"}") + Contract.set_content x.integer + end + """ + + assert %Transaction{data: %TransactionData{content: "42"}} = sanitize_parse_execute(code) + + code = ~S""" + actions triggered_by: transaction do + if Json.parse("42") == 42 do + Contract.set_content "ok" + end + end + """ + + assert %Transaction{data: %TransactionData{content: "ok"}} = sanitize_parse_execute(code) + end + + test "should work with list" do + code = ~S""" + actions triggered_by: transaction do + x = Json.parse("{ \"list\": [1,2,3], \"foo\": \"bar\"}") + Contract.set_content Json.to_string(x.list) + end + """ + + assert %Transaction{data: %TransactionData{content: "[1,2,3]"}} = + sanitize_parse_execute(code) + + code = ~S""" + actions triggered_by: transaction do + x = Json.parse("[1,2,3]") + if List.at(x, 0) == 1 do + Contract.set_content "ok" + end + end + """ + + assert %Transaction{data: %TransactionData{content: "ok"}} = sanitize_parse_execute(code) + end + + test "should work with map" do + code = ~S""" + actions triggered_by: transaction do + x = Json.parse("{ \"map\": {\"foo\" : \"bar\"} }") + Contract.set_content Json.to_string(x.map) + end + """ + + assert %Transaction{data: %TransactionData{content: "{\"foo\":\"bar\"}"}} = + sanitize_parse_execute(code) + end + + test "should work with variable" do + code = ~S""" + actions triggered_by: transaction do + data = "{ \"list\": [1,2,3], \"foo\": \"bar\"}" + x = Json.parse(data) + Contract.set_content Json.to_string(x.list) + end + """ + + assert %Transaction{data: %TransactionData{content: "[1,2,3]"}} = + sanitize_parse_execute(code) + end + + test "should work with affected variable" do + code = ~S""" + actions triggered_by: transaction do + x = Json.parse("{ \"list\": [1,2,3], \"foo\": \"bar\"}") + y = x.list + Contract.set_content Json.to_string(y) + end + """ + + assert %Transaction{data: %TransactionData{content: "[1,2,3]"}} = + sanitize_parse_execute(code) + end + + test "should not parse if parameter is not a string" do + code = ~S""" + actions triggered_by: transaction do + Json.parse(key: "value") + end + """ + + assert {:ok, sanitized_code} = Interpreter.sanitize_code(code) + assert {:error, _, _} = ActionInterpreter.parse(sanitized_code) + end + end + # ---------------------------------------- describe "is_valid?/1" do test "should work" do