Skip to content

Commit cf6e6da

Browse files
committed
implement path page
1 parent 512c57e commit cf6e6da

File tree

12 files changed

+144
-22
lines changed

12 files changed

+144
-22
lines changed

LearnJsonEverything.Tests/ProvidedSolutionTests.cs

+31-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace LearnJsonEverything.Tests;
77

88
public class ProvidedSolutionTests
99
{
10-
private static JsonSerializerOptions SerializerOptions =
10+
private static readonly JsonSerializerOptions SerializerOptions =
1111
new()
1212
{
1313
PropertyNameCaseInsensitive = true
@@ -43,7 +43,36 @@ public static IEnumerable<TestCaseData> SchemaLessons
4343
[TestCaseSource(nameof(SchemaLessons))]
4444
public void Schema(LessonData lesson)
4545
{
46-
var results = SchemaRunner.Run(lesson);
46+
var results = new SchemaHost().Run(lesson);
47+
48+
foreach (var result in results)
49+
{
50+
Console.WriteLine(result);
51+
}
52+
53+
foreach (var result in results)
54+
{
55+
Assert.That(result, Does.StartWith(Iconography.SuccessIcon));
56+
}
57+
}
58+
59+
public static IEnumerable<TestCaseData> PathLessons
60+
{
61+
get
62+
{
63+
var lessonPlan = LoadLessonPlan("path.yaml");
64+
return lessonPlan.Select(x =>
65+
{
66+
x.UserCode = x.Solution;
67+
return new TestCaseData(x) { TestName = x.Title };
68+
});
69+
}
70+
}
71+
72+
[TestCaseSource(nameof(PathLessons))]
73+
public void Path(LessonData lesson)
74+
{
75+
var results = new PathHost().Run(lesson);
4776

4877
foreach (var result in results)
4978
{

LearnJsonEverything.Tests/ReferenceLoader.cs

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
using System.Reflection;
2-
using System.Text.Json.Nodes;
1+
using Json.More;
2+
using Json.Path;
33
using Json.Schema;
44
using Json.Schema.Generation;
55
using Microsoft.CodeAnalysis;
@@ -9,20 +9,19 @@ namespace LearnJsonEverything.Tests;
99

1010
public static class ReferenceLoader
1111
{
12-
private class NullRunner : ILessonRunner<int>
13-
{
14-
public int Run(JsonObject context) => 0;
15-
}
16-
1712
static ReferenceLoader()
1813
{
1914
// force some assemblies to load
20-
SchemaRegistry.Global.Fetch = null!;
15+
Load<ILessonRunner<int>>();
16+
Load<EnumStringConverter<DayOfWeek>>();
17+
Load<JsonSchema>();
18+
Load<MinimumAttribute>();
19+
Load<JsonPath>();
2120
_ = YamlSerializer.Parse(string.Empty);
22-
_ = new NullRunner();
23-
_ = typeof(NullRunner).GetCustomAttributes<MinimumAttribute>();
2421
}
2522

23+
private static void Load<T>(){}
24+
2625
public static MetadataReference[] Load()
2726
{
2827
var refs = AppDomain.CurrentDomain.GetAssemblies();

LearnJsonEverything/LearnJsonEverything.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<ItemGroup>
1515
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
1616
<PackageReference Include="BlazorMonaco" Version="3.2.0" />
17+
<PackageReference Include="JsonPath.Net" Version="1.1.0" />
1718
<PackageReference Include="JsonSchema.Net" Version="7.0.4" />
1819
<PackageReference Include="JsonSchema.Net.Generation" Version="4.3.0.2" />
1920
<PackageReference Include="Markdig" Version="0.37.0" />

LearnJsonEverything/Pages/Path.razor

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@page "/json-path"
2+
@using LearnJsonEverything.Services.Runners
3+
4+
<Teacher LessonSource="/data/lessons/path.yaml" Host="@_host"></Teacher>
5+
6+
@code {
7+
private readonly ILessonHost _host = new PathHost();
8+
}
+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
@page "/json-schema"
2+
@using LearnJsonEverything.Services.Runners
23

3-
<Teacher LessonSource="/data/lessons/schema.yaml"></Teacher>
4+
<Teacher LessonSource="/data/lessons/schema.yaml" Host="@_host"></Teacher>
45

56
@code {
6-
7+
private readonly ILessonHost _host = new SchemaHost();
78
}

LearnJsonEverything/Services/CompilationHelpers.cs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public static class CompilationHelpers
1515
private static readonly string[] EnsuredAssemblies =
1616
[
1717
"Json.More",
18+
"JsonPath.Net",
1819
"JsonPointer.Net",
1920
"JsonSchema.Net",
2021
"JsonSchema.Net.Generation",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace LearnJsonEverything.Services.Runners;
2+
3+
public interface ILessonHost
4+
{
5+
string[] Run(LessonData lesson);
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Json.More;
2+
using Json.Path;
3+
4+
namespace LearnJsonEverything.Services.Runners;
5+
6+
public class PathHost : ILessonHost
7+
{
8+
public string[] Run(LessonData lesson)
9+
{
10+
var (runner, errors) = CompilationHelpers.GetRunner<PathResult>(lesson);
11+
12+
if (runner is null) return errors;
13+
14+
var results = new List<string>();
15+
16+
var correct = true;
17+
foreach (var test in lesson.Tests)
18+
{
19+
var expectedResult = test!["result"];
20+
var result = runner.Run(test.AsObject());
21+
var localResult = expectedResult.IsEquivalentTo(result.Matches?.Select(x => x.Value).ToJsonArray());
22+
correct &= localResult;
23+
results.Add($"{(localResult ? Iconography.SuccessIcon : Iconography.ErrorIcon)} {test["data"]!.Print()}");
24+
}
25+
26+
lesson.Achieved |= correct;
27+
28+
return [.. results];
29+
}
30+
}

LearnJsonEverything/Services/Runners/SchemaRunner.cs renamed to LearnJsonEverything/Services/Runners/SchemaHost.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
namespace LearnJsonEverything.Services.Runners;
44

5-
public static class SchemaRunner
5+
public class SchemaHost : ILessonHost
66
{
7-
public static string[] Run(LessonData lesson)
7+
public string[] Run(LessonData lesson)
88
{
99
var (runner, errors) = CompilationHelpers.GetRunner<EvaluationResults>(lesson);
1010

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

2626
return [.. results];
2727
}
28-
}
28+
}

LearnJsonEverything/Shared/NavMenu.razor

+1-4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77
<div class="feature-description text-muted-light">Constraints-based validation of JSON data</div>
88
</div>
99
</NavLink>
10-
<NavLink class="col mx-3 text-center btn-primary header-btn disabled" href="json-path">
11-
<div class="stamp">
12-
COMING SOON
13-
</div>
10+
<NavLink class="col mx-3 text-center btn-primary header-btn" href="json-path">
1411
<div>
1512
<div>JSON Path</div>
1613
<div class="feature-description text-muted-light">Query JSON data - "XPath for JSON"</div>

LearnJsonEverything/Shared/Teacher.razor

+3-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171

7272
[Parameter]
7373
public string LessonSource { get; set; }
74+
[Parameter]
75+
public ILessonHost Host { get; set; }
7476

7577
private string Instructions { get; set; }
7678

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

9092
_currentLesson!.UserCode = userCode;
91-
var results = SchemaRunner.Run(_currentLesson);
93+
var results = Host.Run(_currentLesson);
9294

9395
await _outputEditor.SetValue(string.Join(Environment.NewLine, results!));
9496
UpdateNavigation();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
- id: 26b6ebca-58e6-4814-86ea-494ed844c9a8
3+
background: |
4+
JSON Path is a syntax for querying JSON data.
5+
6+
_JsonPath.Net_ provides an implementation that conforms to the official IETF
7+
specification, [RFC 9535](https://www.rfc-editor.org/rfc/rfc9535.html). Like the other
8+
guides on this site, this guide will teach you how to use the library _JsonPath.Net_.
9+
10+
However, because there are so few implementations of the RFC, and little to no
11+
documentation of it, this guide will also teach you the features of JSON Path itself,
12+
as described by the RFC.
13+
14+
We'll start with the library since there is less to cover, then we'll move on to
15+
what you can do with it.
16+
17+
Unlike JSON Schema, JSON Logic, or other technologies that are actually represented in
18+
JSON, JSON Path is its own syntax, so it must usually be parsed. The primary way to
19+
parse a path is using the static `JsonPath.Parse()` method.
20+
docs: 'path/basics'
21+
title: Parsing
22+
instructions: |
23+
Parse the given JSON Path text into a `path` variable.
24+
inputTemplate: ''
25+
contextCode: |-
26+
using System.Text.Json;
27+
using System.Text.Json.Nodes;
28+
using Json.Path;
29+
30+
namespace LearnJsonEverything;
31+
32+
public class Lesson : ILessonRunner<PathResult>
33+
{
34+
public PathResult Run(JsonObject test)
35+
{
36+
var data = test["data"];
37+
var pathText = "$.foo.bar";
38+
39+
/* USER CODE */
40+
41+
return path.Evaluate(data);
42+
}
43+
}
44+
solution: |-
45+
var path = JsonPath.Parse(pathText);
46+
tests:
47+
- data: { "foo": { "bar": "a string" } }
48+
result: ['a string']

0 commit comments

Comments
 (0)