fix: add `int` and `string` management on `%json_add`

That fixes:
- https://github.com/plantuml/plantuml/issues/328#issuecomment-2071079413

Here is a fix for `int` and `string`, in order to manage:

```puml
%json_add({"age" : 30}, name, 123) '=> {"age":30,"name":123}
```

```puml
%json_add({"age" : 30}, name, Sally) '=> {"age":30,"name":"Sally"}
```

[FYI @philCryoport]
Reagrds,
Th.
This commit is contained in:
The-Lum 2024-04-24 19:52:11 +00:00
parent 81e7e76c50
commit 6c4eaebd8f
4 changed files with 80 additions and 9 deletions

View File

@ -36,6 +36,7 @@ package net.sourceforge.plantuml.tim.expression;
import java.util.Objects;
import net.sourceforge.plantuml.json.Json;
import net.sourceforge.plantuml.json.JsonValue;
public final class TValue {
@ -221,4 +222,13 @@ public final class TValue {
return jsonValue;
}
public JsonValue toJsonValue() {
if (isNumber()) {
return Json.value(this.intValue);
}
if (isString()) {
return Json.value(this.stringValue);
}
return this.jsonValue;
}
}

View File

@ -72,17 +72,15 @@ public class JsonAdd extends SimpleReturnFunction {
if (!json.isArray() && !json.isObject())
return data;
if (json.isArray()) {
final JsonValue value = values.get(1).toJson();
final JsonArray array = (JsonArray) json;
array.add(value);
return TValue.fromJson(array);
final JsonValue value = values.get(1).toJsonValue();
json.asArray().add(value);
return TValue.fromJson(json);
}
if (json.isObject()) {
final String name = values.get(1).toString();
final JsonValue value = values.get(2).toJson();
final JsonObject object = (JsonObject) json;
object.add(name, value);
return TValue.fromJson(object);
final JsonValue value = values.get(2).toJsonValue();
json.asObject().add(name, value);
return TValue.fromJson(json);
}
throw new EaterException("Bad JSON type", location);
}

View File

@ -83,4 +83,18 @@ public class TimTestUtils {
assertEquals(expected, tValue.toString());
}
// Tfunc: (JsonValue, String, String) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, JsonValue input1, String input2, String input3, String expected) throws EaterException {
final List<TValue> values = Arrays.asList(TValue.fromJson(input1), TValue.fromString(input2), TValue.fromString(input3));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}
// Tfunc: (JsonValue, String, Int) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, JsonValue input1, String input2, Integer input3, String expected) throws EaterException {
final List<TValue> values = Arrays.asList(TValue.fromJson(input1), TValue.fromString(input2), TValue.fromInt(input3));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}
}

View File

@ -38,7 +38,35 @@ class JsonAddTest {
void Test_with_Array_Json(@ConvertWith(StringJsonConverter.class) JsonValue input1, @ConvertWith(StringJsonConverter.class) JsonValue input2, String expected) throws EaterException {
assertTimExpectedOutputFromInput(cut, input1, input2, expected);
}
@ParameterizedTest(name = paramTestName)
@CsvSource(value = {
" [], -1, '[\"-1\"]' ",
" [], 1, '[\"1\"]' ",
" [0], 123, '[0,\"123\"]' ",
" [0], a, '[0,\"a\"]' ",
" [0], \"a\", '[0,\"\\\"a\\\"\"]' ",
" [0], a b c, '[0,\"a b c\"]' ",
" [0], \"a b c\", '[0,\"\\\"a b c\\\"\"]' ",
" '[{\"a\":[1, 2]}]', 1, '[{\"a\":[1,2]},\"1\"]' ",
" '[{\"a\":[1, 2]}]', a, '[{\"a\":[1,2]},\"a\"]' ",
})
void Test_with_Array_Json_add_Str(@ConvertWith(StringJsonConverter.class) JsonValue input1, String input2, String expected) throws EaterException {
assertTimExpectedOutputFromInput(cut, input1, input2, expected);
}
@ParameterizedTest(name = paramTestName)
@CsvSource(value = {
" [], -1, [-1]",
" [], 1, [1]",
" [0], 123, '[0,123]' ",
" '[{\"a\":[1, 2]}]', 1, '[{\"a\":[1,2]},1]' ",
" '[{\"a\":[1, 2]}]', 123, '[{\"a\":[1,2]},123]' ",
})
void Test_with_Array_Json_add_Int(@ConvertWith(StringJsonConverter.class) JsonValue input1, Integer input2, String expected) throws EaterException {
assertTimExpectedOutputFromInput(cut, input1, input2, expected);
}
@ParameterizedTest(name = "[{index}] " + cutName + "({0}, {1}, {2}) = {3}")
@CsvSource(value = {
" {}, a, 1, {\"a\":1}",
@ -57,6 +85,27 @@ class JsonAddTest {
assertTimExpectedOutputFromInput(cut, input1, input2, input3, expected);
}
@ParameterizedTest(name = "[{index}] " + cutName + "({0}, {1}, {2}) = {3}")
@CsvSource(value = {
" {}, a, 1, {\"a\":\"1\"}",
" {}, a, 'abc', '{\"a\":\"abc\"}'",
" {}, a, 'a b c', '{\"a\":\"a b c\"}'",
" {\"age\" : 30}, name, Sally, '{\"age\":30,\"name\":\"Sally\"}'",
})
void Test_with_Object_Json_add_Str(@ConvertWith(StringJsonConverter.class) JsonValue input1, String input2, String input3, String expected) throws EaterException {
assertTimExpectedOutputFromInput(cut, input1, input2, input3, expected);
}
@ParameterizedTest(name = "[{index}] " + cutName + "({0}, {1}, {2}) = {3}")
@CsvSource(value = {
" {}, a, 1, {\"a\":1}",
" {}, a, 123, '{\"a\":123}'",
" {\"age\" : 30}, name, 123, '{\"age\":30,\"name\":123}'",
})
void Test_with_Object_Json_add_Int(@ConvertWith(StringJsonConverter.class) JsonValue input1, String input2, Integer input3, String expected) throws EaterException {
assertTimExpectedOutputFromInput(cut, input1, input2, input3, expected);
}
@Nested
class Not_Nominal_Test {
@ParameterizedTest(name = paramTestName)