Skip to content

Commit

Permalink
implement path page
Browse files Browse the repository at this point in the history
  • Loading branch information
gregsdennis committed Jun 9, 2024
1 parent 512c57e commit cf6e6da
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 22 deletions.
33 changes: 31 additions & 2 deletions LearnJsonEverything.Tests/ProvidedSolutionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace LearnJsonEverything.Tests;

public class ProvidedSolutionTests
{
private static JsonSerializerOptions SerializerOptions =
private static readonly JsonSerializerOptions SerializerOptions =
new()
{
PropertyNameCaseInsensitive = true
Expand Down Expand Up @@ -43,7 +43,36 @@ public static IEnumerable<TestCaseData> SchemaLessons
[TestCaseSource(nameof(SchemaLessons))]
public void Schema(LessonData lesson)
{
var results = SchemaRunner.Run(lesson);
var results = new SchemaHost().Run(lesson);

foreach (var result in results)
{
Console.WriteLine(result);
}

foreach (var result in results)
{
Assert.That(result, Does.StartWith(Iconography.SuccessIcon));
}
}

public static IEnumerable<TestCaseData> PathLessons
{
get
{
var lessonPlan = LoadLessonPlan("path.yaml");
return lessonPlan.Select(x =>
{
x.UserCode = x.Solution;
return new TestCaseData(x) { TestName = x.Title };
});
}
}

[TestCaseSource(nameof(PathLessons))]
public void Path(LessonData lesson)
{
var results = new PathHost().Run(lesson);

foreach (var result in results)
{
Expand Down
19 changes: 9 additions & 10 deletions LearnJsonEverything.Tests/ReferenceLoader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Reflection;
using System.Text.Json.Nodes;
using Json.More;
using Json.Path;
using Json.Schema;
using Json.Schema.Generation;
using Microsoft.CodeAnalysis;
Expand All @@ -9,20 +9,19 @@ namespace LearnJsonEverything.Tests;

public static class ReferenceLoader
{
private class NullRunner : ILessonRunner<int>
{
public int Run(JsonObject context) => 0;
}

static ReferenceLoader()
{
// force some assemblies to load
SchemaRegistry.Global.Fetch = null!;
Load<ILessonRunner<int>>();
Load<EnumStringConverter<DayOfWeek>>();
Load<JsonSchema>();
Load<MinimumAttribute>();
Load<JsonPath>();
_ = YamlSerializer.Parse(string.Empty);
_ = new NullRunner();
_ = typeof(NullRunner).GetCustomAttributes<MinimumAttribute>();
}

private static void Load<T>(){}

public static MetadataReference[] Load()
{
var refs = AppDomain.CurrentDomain.GetAssemblies();
Expand Down
1 change: 1 addition & 0 deletions LearnJsonEverything/LearnJsonEverything.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<ItemGroup>
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageReference Include="BlazorMonaco" Version="3.2.0" />
<PackageReference Include="JsonPath.Net" Version="1.1.0" />
<PackageReference Include="JsonSchema.Net" Version="7.0.4" />
<PackageReference Include="JsonSchema.Net.Generation" Version="4.3.0.2" />
<PackageReference Include="Markdig" Version="0.37.0" />
Expand Down
8 changes: 8 additions & 0 deletions LearnJsonEverything/Pages/Path.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@page "/json-path"
@using LearnJsonEverything.Services.Runners

<Teacher LessonSource="/data/lessons/path.yaml" Host="@_host"></Teacher>

@code {
private readonly ILessonHost _host = new PathHost();
}
5 changes: 3 additions & 2 deletions LearnJsonEverything/Pages/Schema.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
@page "/json-schema"
@using LearnJsonEverything.Services.Runners

<Teacher LessonSource="/data/lessons/schema.yaml"></Teacher>
<Teacher LessonSource="/data/lessons/schema.yaml" Host="@_host"></Teacher>

@code {

private readonly ILessonHost _host = new SchemaHost();
}
1 change: 1 addition & 0 deletions LearnJsonEverything/Services/CompilationHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static class CompilationHelpers
private static readonly string[] EnsuredAssemblies =
[
"Json.More",
"JsonPath.Net",
"JsonPointer.Net",
"JsonSchema.Net",
"JsonSchema.Net.Generation",
Expand Down
6 changes: 6 additions & 0 deletions LearnJsonEverything/Services/Runners/ILessonHost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace LearnJsonEverything.Services.Runners;

public interface ILessonHost
{
string[] Run(LessonData lesson);
}
30 changes: 30 additions & 0 deletions LearnJsonEverything/Services/Runners/PathHost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Json.More;
using Json.Path;

namespace LearnJsonEverything.Services.Runners;

public class PathHost : ILessonHost
{
public string[] Run(LessonData lesson)
{
var (runner, errors) = CompilationHelpers.GetRunner<PathResult>(lesson);

if (runner is null) return errors;

var results = new List<string>();

var correct = true;
foreach (var test in lesson.Tests)
{
var expectedResult = test!["result"];
var result = runner.Run(test.AsObject());
var localResult = expectedResult.IsEquivalentTo(result.Matches?.Select(x => x.Value).ToJsonArray());
correct &= localResult;
results.Add($"{(localResult ? Iconography.SuccessIcon : Iconography.ErrorIcon)} {test["data"]!.Print()}");
}

lesson.Achieved |= correct;

return [.. results];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

namespace LearnJsonEverything.Services.Runners;

public static class SchemaRunner
public class SchemaHost : ILessonHost
{
public static string[] Run(LessonData lesson)
public string[] Run(LessonData lesson)
{
var (runner, errors) = CompilationHelpers.GetRunner<EvaluationResults>(lesson);

Expand All @@ -25,4 +25,4 @@ public static string[] Run(LessonData lesson)

return [.. results];
}
}
}
5 changes: 1 addition & 4 deletions LearnJsonEverything/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
<div class="feature-description text-muted-light">Constraints-based validation of JSON data</div>
</div>
</NavLink>
<NavLink class="col mx-3 text-center btn-primary header-btn disabled" href="json-path">
<div class="stamp">
COMING SOON
</div>
<NavLink class="col mx-3 text-center btn-primary header-btn" href="json-path">
<div>
<div>JSON Path</div>
<div class="feature-description text-muted-light">Query JSON data - "XPath for JSON"</div>
Expand Down
4 changes: 3 additions & 1 deletion LearnJsonEverything/Shared/Teacher.razor
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@

[Parameter]
public string LessonSource { get; set; }
[Parameter]
public ILessonHost Host { get; set; }

private string Instructions { get; set; }

Expand All @@ -88,7 +90,7 @@
await _outputEditor.SetLanguageAsync("json", JsRuntime);

_currentLesson!.UserCode = userCode;
var results = SchemaRunner.Run(_currentLesson);
var results = Host.Run(_currentLesson);

await _outputEditor.SetValue(string.Join(Environment.NewLine, results!));
UpdateNavigation();
Expand Down
48 changes: 48 additions & 0 deletions LearnJsonEverything/wwwroot/data/lessons/path.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
- id: 26b6ebca-58e6-4814-86ea-494ed844c9a8
background: |
JSON Path is a syntax for querying JSON data.
_JsonPath.Net_ provides an implementation that conforms to the official IETF
specification, [RFC 9535](https://www.rfc-editor.org/rfc/rfc9535.html). Like the other
guides on this site, this guide will teach you how to use the library _JsonPath.Net_.
However, because there are so few implementations of the RFC, and little to no
documentation of it, this guide will also teach you the features of JSON Path itself,
as described by the RFC.
We'll start with the library since there is less to cover, then we'll move on to
what you can do with it.
Unlike JSON Schema, JSON Logic, or other technologies that are actually represented in
JSON, JSON Path is its own syntax, so it must usually be parsed. The primary way to
parse a path is using the static `JsonPath.Parse()` method.
docs: 'path/basics'
title: Parsing
instructions: |
Parse the given JSON Path text into a `path` variable.
inputTemplate: ''
contextCode: |-
using System.Text.Json;
using System.Text.Json.Nodes;
using Json.Path;
namespace LearnJsonEverything;
public class Lesson : ILessonRunner<PathResult>
{
public PathResult Run(JsonObject test)
{
var data = test["data"];
var pathText = "$.foo.bar";
/* USER CODE */
return path.Evaluate(data);
}
}
solution: |-
var path = JsonPath.Parse(pathText);
tests:
- data: { "foo": { "bar": "a string" } }
result: ['a string']

0 comments on commit cf6e6da

Please sign in to comment.