diff --git a/YetAnother.Web/JsonToYamlConverter.cs b/YetAnother.Web/JsonToYamlConverter.cs index 8ebaf12..adb4baf 100644 --- a/YetAnother.Web/JsonToYamlConverter.cs +++ b/YetAnother.Web/JsonToYamlConverter.cs @@ -20,32 +20,51 @@ public class JsonToYamlConverter }; private EmitterSettings emitterSettings = new EmitterSettings( - bestIndent: 2, + bestIndent: 2, bestWidth: 120, isCanonical: false, maxSimpleKeyLength: 120, skipAnchorName: false, indentSequences: false, - newLine: null) - { - - }; + newLine: null + ); - public JToken ParseJson(string? json) + public IEnumerable ParseJson(string? json) { - return JToken.Parse(json ?? "", jsonLoadSettings); + var tokens = new List(); + var reader = new JsonTextReader(new StringReader(json)); + tokens.Add(JToken.Load(reader, jsonLoadSettings)); + while (reader.Read()) + { + tokens.Add(JToken.Load(reader, jsonLoadSettings)); + } + return tokens; } - public string ConvertToYaml(JToken token) + public string ConvertToYaml(IEnumerable tokens) { using var stringWriter = new StringWriter(); var emitter = new Emitter(stringWriter, emitterSettings); emitter.Emit(new StreamStart()); emitter.Emit(new DocumentStart()); + bool gotFirstNonComment = false; + try { - EmitJTokenToYaml(emitter, token); + foreach (var token in tokens) + { + if (token.Type != JTokenType.Comment) + { + if (gotFirstNonComment) + { + emitter.Emit(new DocumentEnd(false)); + emitter.Emit(new DocumentStart()); + } + gotFirstNonComment = true; + } + EmitJTokenHierarchyToYaml(emitter, token); + } } catch (Exception ex) { @@ -57,9 +76,9 @@ public string ConvertToYaml(JToken token) return stringWriter.ToString(); } - private void EmitJTokenToYaml(IEmitter emitter, JToken token, JTokenReader? reader = null) + private void EmitJTokenHierarchyToYaml(IEmitter emitter, JToken token) { - reader ??= new JTokenReader(token); + var reader = new JTokenReader(token); int previousLine = -1; while (reader.Read()) @@ -71,91 +90,99 @@ private void EmitJTokenToYaml(IEmitter emitter, JToken token, JTokenReader? read previousLine = currentLineNumber; } - TagName tag = TagName.Empty; + EmitJTokenToYaml(emitter, reader, currentLineNumber, isOnNewLine, reader.CurrentToken); + } + } - switch (reader.TokenType) - { - case JsonToken.None: - break; - - case JsonToken.StartObject: - tag = FailsafeSchema.Tags.Map; - JContainer jobject = (JContainer?)reader.CurrentToken ?? throw new JsonSerializationException(); - MappingStyle mappingStyle = MappingStyle.Any; - if (jobject.Last?.GetLineNumber() == currentLineNumber) - { - mappingStyle = MappingStyle.Flow; - } - emitter.Emit(new MappingStart(AnchorName.Empty, tag, true, mappingStyle)); - break; - - case JsonToken.StartArray: - tag = FailsafeSchema.Tags.Seq; - JContainer jarray = (JContainer?)reader.CurrentToken ?? throw new JsonSerializationException(); - SequenceStyle sequenceStyle = SequenceStyle.Any; - if (jarray.Last?.GetLineNumber() == currentLineNumber) - { - sequenceStyle = SequenceStyle.Flow; - } - emitter.Emit(new SequenceStart(AnchorName.Empty, TagName.Empty, true, sequenceStyle)); - break; - - case JsonToken.StartConstructor: - throw new NotSupportedException(reader.TokenType.ToString()); - break; - - case JsonToken.PropertyName: - tag = FailsafeSchema.Tags.Str; - EmitPropertyNameToYaml(emitter, reader.Value as string ?? string.Empty, reader.CurrentToken!); - break; - - case JsonToken.Comment: - emitter.Emit(new Comment(reader.Value?.ToString() ?? string.Empty, !isOnNewLine)); - break; - - case JsonToken.Raw: - throw new NotSupportedException(reader.TokenType.ToString()); - break; - - case JsonToken.String: - EmitStringToYaml(emitter, reader.Value as string ?? string.Empty, reader.CurrentToken!); - break; - - case JsonToken.Integer: - tag = JsonSchema.Tags.Int; - goto case JsonToken.Undefined; - case JsonToken.Float: - tag = JsonSchema.Tags.Float; - goto case JsonToken.Undefined; - case JsonToken.Boolean: - tag = JsonSchema.Tags.Bool; - goto case JsonToken.Undefined; - case JsonToken.Null: - tag = JsonSchema.Tags.Null; - goto case JsonToken.Undefined; - case JsonToken.Date: - tag = DefaultSchema.Tags.Timestamp; - goto case JsonToken.Undefined; - case JsonToken.Undefined: - emitter.Emit(new Scalar(AnchorName.Empty, tag, reader.Value?.ToString() ?? string.Empty, - ScalarStyle.Any, isPlainImplicit: true, isQuotedImplicit: true)); - break; - - case JsonToken.EndObject: - emitter.Emit(new MappingEnd()); - break; - - case JsonToken.EndArray: - emitter.Emit(new SequenceEnd()); - break; - - case JsonToken.EndConstructor: - case JsonToken.Bytes: - throw new NotSupportedException(reader.TokenType.ToString()); - break; + private void EmitJTokenToYaml(IEmitter emitter, JsonReader reader, int currentLineNumber, bool isOnNewLine, JToken? currentToken = null) + { + TagName tag = TagName.Empty; + Console.WriteLine($"Token Type: {reader.TokenType}"); + + switch (reader.TokenType) + { + case JsonToken.None: + break; + + case JsonToken.StartObject: + tag = FailsafeSchema.Tags.Map; + JContainer? jobject = (JContainer?)currentToken; + MappingStyle mappingStyle = MappingStyle.Any; + if (jobject?.Last?.GetLineNumber() == currentLineNumber) + { + mappingStyle = MappingStyle.Flow; + } + emitter.Emit(new MappingStart(AnchorName.Empty, tag, true, mappingStyle)); + break; + + case JsonToken.StartArray: + tag = FailsafeSchema.Tags.Seq; + JContainer? jarray = (JContainer?)currentToken; + SequenceStyle sequenceStyle = SequenceStyle.Any; + if (jarray?.Last?.GetLineNumber() == currentLineNumber) + { + sequenceStyle = SequenceStyle.Flow; + } + emitter.Emit(new SequenceStart(AnchorName.Empty, TagName.Empty, true, sequenceStyle)); + break; + + case JsonToken.StartConstructor: + throw new NotSupportedException(reader.TokenType.ToString()); + break; + + case JsonToken.PropertyName: + tag = FailsafeSchema.Tags.Str; + EmitPropertyNameToYaml(emitter, reader.Value as string ?? string.Empty, currentToken); + break; + + case JsonToken.Comment: + Console.WriteLine($"Got a comment {(isOnNewLine ? "newline" : "inline")}: {reader.Value?.ToString()}"); + emitter.Emit(new Comment(reader.Value?.ToString() ?? string.Empty, !isOnNewLine)); + break; + + case JsonToken.Raw: + throw new NotSupportedException(reader.TokenType.ToString()); + break; + + case JsonToken.String: + EmitStringToYaml(emitter, reader.Value as string ?? string.Empty, currentToken); + break; + + case JsonToken.Integer: + tag = JsonSchema.Tags.Int; + goto case JsonToken.Undefined; + case JsonToken.Float: + tag = JsonSchema.Tags.Float; + goto case JsonToken.Undefined; + case JsonToken.Boolean: + tag = JsonSchema.Tags.Bool; + goto case JsonToken.Undefined; + case JsonToken.Null: + tag = JsonSchema.Tags.Null; + goto case JsonToken.Undefined; + case JsonToken.Date: + tag = DefaultSchema.Tags.Timestamp; + goto case JsonToken.Undefined; + case JsonToken.Undefined: + emitter.Emit(new Scalar(AnchorName.Empty, tag, reader.Value?.ToString() ?? string.Empty, + ScalarStyle.Any, isPlainImplicit: true, isQuotedImplicit: true)); + break; + + case JsonToken.EndObject: + emitter.Emit(new MappingEnd()); + break; + + case JsonToken.EndArray: + emitter.Emit(new SequenceEnd()); + break; + + case JsonToken.EndConstructor: + case JsonToken.Bytes: + throw new NotSupportedException(reader.TokenType.ToString()); + break; - } } + } private void EmitPropertyNameToYaml(IEmitter emitter, string str, JToken token) @@ -185,7 +212,7 @@ private void EmitStringToYaml(IEmitter emitter, string str, JToken token) } ScalarStyle style = ScalarStyle.Any; - Console.WriteLine($"path: {token.Path}"); + Console.WriteLine($"path: {token?.Path}"); if (str.Length > emitterSettings.BestWidth && str.Contains(' ')) { diff --git a/YetAnother.Web/Pages/Converter.razor b/YetAnother.Web/Pages/Converter.razor index 553c718..5a9db57 100644 --- a/YetAnother.Web/Pages/Converter.razor +++ b/YetAnother.Web/Pages/Converter.razor @@ -5,6 +5,8 @@

Json to Yaml Converter

+@errorMessage + @@ -26,9 +28,11 @@ + @code { private EditContext? editContext; private JsonToYamlConverter Model { get; set; } = new(); + private string? errorMessage; protected override void OnInitialized() { @@ -37,14 +41,32 @@ private void Submit() { + errorMessage = ""; + if (editContext != null && editContext.Validate()) { - var jtoken = Model.ParseJson(Model.JsonString); - Model.YamlString = Model.ConvertToYaml(jtoken); - Logger.LogInformation("Submit called: Form is valid"); + try + { + var jtokens = Model.ParseJson(Model.JsonString); + Model.YamlString = Model.ConvertToYaml(jtokens); + Logger.LogInformation("Submit called: Form is valid"); + } + catch (JsonException ex) + { + errorMessage = $"Invalid JSON: {ex.Message}"; + } + catch (YamlException ex) + { + errorMessage = $"YAML Error: {ex.Message}"; + } + catch (Exception ex) + { + errorMessage = $"{ex.GetType().Name}: {ex.Message}"; + } } else { + errorMessage = "form is invalid"; Logger.LogInformation("Submit called: Form is INVALID"); } }