Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* feat(json-support): Add Support for System.Text.Json.JsonElement #527 - Introduced JsonElementExtensions.cs to convert JsonElements into Scriban objects - Updated ScriptArray.cs and ScriptObject.cs to handle JsonElements - Enhanced ScriptObjectExtensions.cs with methods for importing JsonElements into script objects - Extended Template.cs with a Render method that accepts a JsonElement as input - Added new test cases to validate JSON support * feat(json-support): Add object.form_json and object.to_json functions #527 - Implemented FromJson function to convert JSON to Scriban value - Implemented ToJson function to convert Scriban value to JSON - Added new test cases for JSON parsing and conversion in TestObjectFunctions.cs * feat(json-support): Updating docs to show new functionality * feat(json-support): Removed unnecessary JSON support from ScriptArray and ScriptObject - Deleted methods that added JsonElement to ScriptArray and ScriptObject - Removed JsonElement handling in Add and SetValue methods of ScriptObject - Erased test cases for adding json values in TestScriptArrayJson.cs and TestScriptObjectJson.cs * chore(json-support): Fix Docs unit test - Updated JSON formatting in builtins.md * feat(json-support): Move JSON handling to import logic - Moved JSON conversion logic to JsonElementExtensions.cs - Removed JSON handling code from ScriptObject.cs to ScriptObjectExtensions.cs import - Added ConvertValue method to handle Scriban value conversions * fix(json-support): Remove explicit ScriptObject.From(JsonElement) method - Deleted method for creating a ScriptObject from a JsonElement as this functionality can be achieved using generic from object method - Removed unused using directives in ScriptObject.cs and ScriptObjectExtensions.cs * fix(json-support): Remove explicit Template.Render JsonElement method - Removed Render method with JsonElement as this can be achieved using the generic render object method - Deleted System.Text.Json usage in Scriban.Template.cs
- Loading branch information
Showing
12 changed files
with
789 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
src/Scriban.Tests/TestJsonSupport/TestModelWithJsonElement.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// Copyright (c) Alexandre Mutel. All rights reserved. | ||
// Licensed under the BSD-Clause 2 license. See license.txt file in the project root for full license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Text.Json; | ||
using Scriban.Runtime; | ||
|
||
|
||
namespace Scriban.Tests.TestJsonSupport; | ||
|
||
[TestFixture] | ||
public class TestModelWithJsonElement { | ||
[TestCase("""null""", "")] | ||
[TestCase("""true""", "true")] | ||
[TestCase("""false""", "false")] | ||
[TestCase("""123.45""", "123.45")] | ||
[TestCase("\"bar\"", "bar")] | ||
[TestCase("""[1, 2, 3]""", "[1, 2, 3]")] | ||
[TestCase("""{ "foo": "bar" }""", "{foo: \"bar\"}")] | ||
public void Can_import_JsonElement_property(string json, string expected) | ||
{ | ||
var jsonElement = JsonSerializer.Deserialize<JsonElement>(json); | ||
|
||
var model = new { | ||
foo = jsonElement, | ||
}; | ||
|
||
var result = RenderHelper.Render( | ||
script: "{{ foo }}", | ||
scriptObject: ScriptObject.From(model) | ||
); | ||
|
||
Assert.AreEqual(expected, result); | ||
} | ||
|
||
[Test] | ||
public void Can_import_boxed_jsonElement() | ||
{ | ||
var model = JsonSerializer.Deserialize<Dictionary<string, object>>("""{ "model": { "foo": "bar" } }"""); | ||
|
||
// ensure we have a boxed JsonElement: | ||
Assert.AreEqual(typeof(string), model.GetType().GetGenericArguments()[0]); | ||
Assert.AreEqual(typeof(object), model.GetType().GetGenericArguments()[1]); | ||
Assert.AreEqual(typeof(JsonElement), model["model"].GetType()); | ||
|
||
var result = RenderHelper.Render( | ||
script: "{{ model.foo }}", | ||
scriptObject: ScriptObject.From(model) | ||
); | ||
|
||
Assert.AreEqual("bar", result); | ||
} | ||
|
||
[Test] | ||
public void Can_import_jsonElement_in_typed_class() | ||
{ | ||
var data = JsonSerializer.Deserialize<JsonElement>("""{ "foo": "bar" }"""); | ||
|
||
var model = new MyClass("name", data); | ||
|
||
var result = RenderHelper.Render( | ||
script: """ | ||
Name: {{ name }} | ||
Data.Foo: {{ data.foo }} | ||
""", | ||
scriptObject: ScriptObject.From(model) | ||
); | ||
|
||
Assert.AreEqual("Name: name\r\nData.Foo: bar", result); | ||
} | ||
|
||
[Test] | ||
public void Can_import_jsonElement_in_typed_struct() | ||
{ | ||
var data = JsonSerializer.Deserialize<JsonElement>("""{ "foo": "bar" }"""); | ||
|
||
var model = new MyStruct("name", data); | ||
|
||
var result = RenderHelper.Render( | ||
script: """ | ||
Name: {{ name }} | ||
Data.Foo: {{ data.foo }} | ||
""", | ||
scriptObject: ScriptObject.From(model) | ||
); | ||
|
||
Assert.AreEqual("Name: name\r\nData.Foo: bar", result); | ||
} | ||
|
||
|
||
private record MyClass( | ||
string Name, | ||
JsonElement Data | ||
); | ||
|
||
private record struct MyStruct( | ||
string Name, | ||
JsonElement Data | ||
); | ||
} |
144 changes: 144 additions & 0 deletions
144
src/Scriban.Tests/TestJsonSupport/TestObjectFunctions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// Copyright (c) Alexandre Mutel. All rights reserved. | ||
// Licensed under the BSD-Clause 2 license. See license.txt file in the project root for full license information. | ||
|
||
using System; | ||
using Scriban.Runtime; | ||
using Scriban.Syntax; | ||
|
||
|
||
namespace Scriban.Tests.TestJsonSupport; | ||
|
||
[TestFixture] | ||
public class TestObjectFunctions { | ||
[Test] | ||
public void Can_parse_json() | ||
{ | ||
var template = Template.Parse(""" | ||
{{ | ||
json = `{ "foo": { "bar": [{ "baz": 1 }, { "baz": 2 }, { "baz": 3 }] } }` | ||
obj = json | object.from_json | ||
obj.foo.bar[1].baz | ||
}} | ||
""" | ||
); | ||
|
||
var result = template.Render(); | ||
|
||
Assert.AreEqual("2", result); | ||
} | ||
|
||
[TestCase(""" | ||
null | ||
""", """ | ||
null | ||
""")] | ||
[TestCase(""" | ||
true | ||
""", """ | ||
true | ||
""")] | ||
[TestCase(""" | ||
false | ||
""", """ | ||
false | ||
""")] | ||
[TestCase(""" | ||
"string" | ||
""", """ | ||
"string" | ||
""")] | ||
[TestCase(""" | ||
123 | ||
""", """ | ||
123 | ||
""")] | ||
[TestCase(""" | ||
123.45 | ||
""", """ | ||
123.45 | ||
""")] | ||
[TestCase(""" | ||
[1, 2, 3, {foo: "bar"}, { "baz": 123 }] | ||
""", """ | ||
[1,2,3,{"foo":"bar"},{"baz":123}] | ||
""")] | ||
[TestCase(""" | ||
{ foo: { bar: [{ baz: 1 }, { baz: 2 }, { baz: 3 }] } } | ||
""", """ | ||
{"foo":{"bar":[{"baz":1},{"baz":2},{"baz":3}]}} | ||
""")] | ||
public void Can_convert_ScribanValue_to_json(string scriban, string json) | ||
{ | ||
var template = Template.Parse($$$""" | ||
{{ {{{scriban}}} | object.to_json }} | ||
""" | ||
); | ||
|
||
var result = template.Render(); | ||
|
||
Assert.AreEqual(json, result); | ||
} | ||
|
||
[Test] | ||
public void Can_convert_TypedModel_to_json() | ||
{ | ||
var template = Template.Parse(""" | ||
{{ model | object.to_json }} | ||
""" | ||
); | ||
|
||
var result = template.Render(new { | ||
Model = new { | ||
Foo = "bar", | ||
Baz = new[] { 1, 2, 3 } | ||
} | ||
}); | ||
|
||
Assert.AreEqual(""" | ||
{"foo":"bar","baz":[1,2,3]} | ||
""", result); | ||
} | ||
|
||
[Test] | ||
public void Can_handle_MemberRenamer_when_writing_json() | ||
{ | ||
var template = Template.Parse(""" | ||
{{ Model | object.to_json }} | ||
""" | ||
); | ||
|
||
var model = new { | ||
Model = new { | ||
Foo = "bar", | ||
Baz = new[] { 1, 2, 3 } | ||
} | ||
}; | ||
|
||
var result = template.Render(model, member => member.Name); | ||
|
||
Assert.AreEqual(""" | ||
{"Foo":"bar","Baz":[1,2,3]} | ||
""", result); | ||
} | ||
|
||
[Test] | ||
public void Throws_when_serializing_function_to_json() | ||
{ | ||
var template = Template.Parse(""" | ||
{{ | ||
func myFunc() | ||
ret 1 | ||
end | ||
|
||
object.to_json @myFunc | ||
}} | ||
""" | ||
); | ||
|
||
var ex = Assert.Throws<ScriptRuntimeException>(() => { | ||
var result = template.Render(); | ||
})!; | ||
|
||
Assert.AreEqual("<input>(6,20) : error : Can not serialize functions to JSON. (Parameter 'value')", ex.Message); | ||
} | ||
} |
Oops, something went wrong.