public static T ProcessRequiredProperty <T>(this JsonElement element, string propertyName, JsonParserContext context, Func <JsonElement, JsonParserContext, T> propertyParser) { Debug.Assert(element.ValueKind == JsonValueKind.Object); T value = default(T); if (element.TryGetProperty(propertyName, out JsonElement propertyValue)) { context.EnterScope(propertyName); value = propertyParser(propertyValue, context); context.LeaveScope(propertyName); } else { context.ReportError(EdmErrorCode.MissingRequiredProperty, Strings.CsdlJsonParser_MissingRequiredPropertyInObject(propertyName, context.Path)); } return(value); }
/// <summary> /// Parser method which parses the top level Json Object which represents the overall Graph /// </summary> /// <param name="context">Parser Context</param> private void ParseGraphObject(JsonParserContext context) { //Can we read the overall Graph Object PositionInfo startPos = context.CurrentPosition; if (context.Input.Read()) { if (context.Input.TokenType == JsonToken.StartObject) { this.ParseTriples(context); //When we get control back we should have already read the last token which should be an End Object //We ignore any content which is beyond the end of the initial object if (context.Input.TokenType != JsonToken.EndObject) { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, end of the JSON Graph Object was expected", startPos); } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, start of the JSON Graph Object was expected", startPos); } } else { throw Error(context, "Unexpected End of Input while trying to parse start of the JSON Graph Object", startPos); } }
/// <summary> /// Internal top level Parse method which parses the JSON /// </summary> /// <param name="g">Graph to read into</param> /// <param name="input">Stream to read from</param> private void Parse(IRdfHandler handler, TextReader input) { //Create Parser Context and parse JsonParserContext context = new JsonParserContext(handler, new CommentIgnoringJsonTextReader(input)); this.ParseTriplesArray(context); }
/// <summary> /// Parser method which parses Json Arrays representing Object Lists /// </summary> /// <param name="context">Parser Context</param> /// <param name="subj">Subject of Triples which comes from the Grandparent Json Object</param> /// <param name="pred">Predicate of Triples which comes form the Parent Json Object</param> private void ParseObjectList(JsonParserContext context, INode subj, INode pred) { PositionInfo startPos = context.CurrentPosition; if (context.Input.Read()) { //Expect an Array for the Object List if (context.Input.TokenType == JsonToken.StartArray) { while (context.Input.TokenType != JsonToken.EndArray) { //Try to parse an 'Object' Object!! this.ParseObject(context, subj, pred); } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected the start of a JSON Array to represent an Object List", startPos); } } else { throw Error(context, "Unexpected End of Input while trying to parse an Object List from the JSON", startPos); } }
private static CsdlExpressionBase ParseExpression(string json, out JsonParserContext context) { using (JsonDocument document = JsonDocument.Parse(json)) { JsonElement rootElement = document.RootElement; context = new JsonParserContext(); return(AnnotationJsonParser.ParseExpression(rootElement, context)); } }
/// <summary> /// Helper method for raising Error messages with attached Position Information /// </summary> /// <param name="context">Parser Context</param> /// <param name="message">Error Message</param> /// <param name="startPos">Start Position</param> /// <returns></returns> private RdfParseException Error(JsonParserContext context, String message, PositionInfo startPos) { PositionInfo info = context.GetPositionRange(startPos); StringBuilder error = new StringBuilder(); error.Append("[Line " + info.StartLine + " Column " + info.StartPosition + " to Line " + info.EndLine + " Column " + info.EndPosition + "] "); error.AppendLine(message); throw new RdfParseException(error.ToString(), info); }
public void ParseValidVersionStringWorksAsExpected(string version) { string json = @"{""$Version"":""" + version + @"""}"; Utf8JsonReader jsonReader = GetJsonReader(json); JsonParserContext context = new JsonParserContext(); CsdlModel csdlModel = CsdlJsonParser.ParseCsdlDocument(ref jsonReader, context); Assert.Equal(version == "4.0" ? EdmConstants.EdmVersion4 : EdmConstants.EdmVersion401, csdlModel.CsdlVersion); }
public static string ParseAsString(this JsonElement element, JsonParserContext context) { if (element.ValueKind == JsonValueKind.String || element.ValueKind == JsonValueKind.Null) { return(element.GetString()); } context.ReportError(EdmErrorCode.UnexpectedValueKind, Strings.CsdlJsonParser_UnexpectedJsonValueKind(element.ValueKind, context.Path, "String")); return(null); }
public static int?ParseAsInteger(this JsonElement element, JsonParserContext context) { if (element.ValueKind == JsonValueKind.Number) { return(element.GetInt32()); } context.ReportError(EdmErrorCode.UnexpectedValueKind, Strings.CsdlJsonParser_UnexpectedJsonValueKind(element.ValueKind, context.Path, "Integer")); return(default(int?)); }
/// <summary> /// Load and parse the referenced model but ignored any further referenced model. /// </summary> /// <param name="csdlModel">The main CSDL model.</param> /// <param name="context">The parser context.</param> /// <returns>A list of CsdlModel (no semantics) of the referenced models.</returns> private static List <CsdlModel> LoadReferencedCsdl(CsdlModel csdlModel, JsonParserContext context) { List <CsdlModel> referencedAstModels = new List <CsdlModel>(); if (context.Settings.JsonSchemaReaderFactory == null) { // don't try to load CSDL-JSON doc, but this.edmReferences's namespace-alias need to be used later. return(referencedAstModels); } foreach (var edmReference in csdlModel.CurrentModelReferences) { // If nothing included, why does it exist? if (!edmReference.Includes.Any() && !edmReference.IncludeAnnotations.Any()) { continue; } // Skip the built-in vocabulary annotation model if (edmReference.Uri != null && (edmReference.Uri.OriginalString.EndsWith("/Org.OData.Core.V1.json", StringComparison.Ordinal) || edmReference.Uri.OriginalString.EndsWith("/Org.OData.Capabilities.V1.json", StringComparison.Ordinal) || edmReference.Uri.OriginalString.EndsWith("/Org.OData.Authorization.V1.json", StringComparison.Ordinal) || edmReference.Uri.OriginalString.EndsWith("/Org.OData.Validation.V1.json", StringComparison.Ordinal) || edmReference.Uri.OriginalString.EndsWith("/Org.OData.Community.V1.json", StringComparison.Ordinal) || edmReference.Uri.OriginalString.EndsWith("/OData.Community.Keys.V1.json", StringComparison.Ordinal))) { continue; } Utf8JsonReader referencedJsonReader = context.Settings.JsonSchemaReaderFactory(edmReference.Uri, out bool skip); if (!skip) { string source = edmReference.Uri != null ? edmReference.Uri.OriginalString : null; CsdlJsonReaderSettings newSettings = context.Settings.Clone(); // set it to null to make sure stop the next level reference parsing. newSettings.JsonSchemaReaderFactory = null; JsonParserContext subContext = new JsonParserContext(newSettings, source); CsdlModel subCsdlModel = CsdlJsonParser.ParseCsdlDocument(ref referencedJsonReader, subContext); if (subCsdlModel != null && subContext.IsSucceeded()) { // Should we compare the referenced version with the main CSDL version and report error if mismatching? // So far, it's fine to ignore, because there may be scenarios where referenced schemas are at a different version. subCsdlModel.AddParentModelReferences(edmReference); referencedAstModels.Add(subCsdlModel); } context.AddRange(subContext.Errors); } } return(referencedAstModels); }
public static bool?ParseAsBoolean(this JsonElement element, JsonParserContext context) { if (element.ValueKind == JsonValueKind.True || element.ValueKind == JsonValueKind.False) { return(element.GetBoolean()); } context.ReportError(EdmErrorCode.UnexpectedValueKind, Strings.CsdlJsonParser_UnexpectedJsonValueKind(element.ValueKind, context.Path, "Boolean")); return(null); }
/// <summary> /// Helper method for raising Error messages with attached Line Information /// </summary> /// <param name="context">Parser Context</param> /// <param name="message">Error Message</param> /// <returns></returns> private RdfParseException Error(JsonParserContext context, String message) { StringBuilder error = new StringBuilder(); if (context.Input.HasLineInfo()) { error.Append("[Line " + context.Input.LineNumber + " Column " + context.Input.LinePosition + "] "); } error.AppendLine(context.Input.TokenType.GetType().Name); error.Append(message); throw new RdfParseException(error.ToString(), context.Input.LineNumber, context.Input.LinePosition); }
public void InvalidCsdlDocumentJsonValueKindReportingJsonInvalidValueKindError() { string json = @" [ {""$Version"": ""4.01""} ]"; Utf8JsonReader jsonReader = GetJsonReader(json); JsonParserContext context = new JsonParserContext(); CsdlJsonParser.ParseCsdlDocument(ref jsonReader, context); EdmError error = Assert.Single(context.Errors); Assert.Equal(EdmErrorCode.UnexpectedValueKind, error.ErrorCode); Assert.Equal("An unexpected 'Array' value kind was found when parsing the JSON path '$'. A 'Object' value kind was expected.", error.ErrorMessage); }
public void UnexpectedJsonMemberReportingJsonUnexpectedJsonMemberError() { string json = @" {""$Version"": ""4.01"", ""Anything"": 1.0 }"; Utf8JsonReader jsonReader = GetJsonReader(json); JsonParserContext context = new JsonParserContext(); CsdlJsonParser.ParseCsdlDocument(ref jsonReader, context); EdmError error = Assert.Single(context.Errors); Assert.Equal(EdmErrorCode.UnexpectedElement, error.ErrorCode); Assert.Equal("A member '$.Anything' with value type 'Number' is unexpected.", error.ErrorMessage); }
public static T ProcessItem <T>(this JsonElement element, int index, JsonParserContext context, Func <JsonElement, JsonParserContext, T> parser) { Debug.Assert(element.ValueKind == JsonValueKind.Array); context.EnterScope(index); T ret = parser(element[index], context); context.LeaveScope(); return(ret); }
public void InvalidVersionValueReportingUnexpectedValueKind() { string json = @" { ""$Version"": ""5.0"" }"; Utf8JsonReader jsonReader = GetJsonReader(json); JsonParserContext context = new JsonParserContext(); CsdlJsonParser.ParseCsdlDocument(ref jsonReader, context); EdmError error = Assert.Single(context.Errors); Assert.Equal(EdmErrorCode.InvalidVersionNumber, error.ErrorCode); Assert.Equal("The version specified at '$.$Version' is not valid. It should be a string containing either '4.0' or '4.01'.", error.ErrorMessage); }
public void InvalidVersionValueKindReportingUnexpectedValueKind() { string json = @" { ""$Version"": 4.01 }"; Utf8JsonReader jsonReader = GetJsonReader(json); JsonParserContext context = new JsonParserContext(); CsdlJsonParser.ParseCsdlDocument(ref jsonReader, context); EdmError error = Assert.Single(context.Errors); Assert.Equal(EdmErrorCode.UnexpectedValueKind, error.ErrorCode); Assert.Equal("An unexpected 'Number' value kind was found when parsing the JSON path '$.$Version'. A 'String' value kind was expected.", error.ErrorMessage); }
public void MissingVersionReportingMissingRequiredPropertyError() { string json = @" { }"; Utf8JsonReader jsonReader = GetJsonReader(json); JsonParserContext context = new JsonParserContext(); CsdlJsonParser.ParseCsdlDocument(ref jsonReader, context); EdmError error = Assert.Single(context.Errors); Assert.Equal(EdmErrorCode.MissingRequiredProperty, error.ErrorCode); Assert.Equal("A property '$Version' is missing when parsing the JSON path '$'.", error.ErrorMessage); }
private static T ParseCsdlSchemaElement <T>(string json, Func <string, JsonElement, JsonParserContext, T> parser) { string wrapper = "{" + json + "}"; using (JsonDocument document = JsonDocument.Parse(wrapper)) { JsonElement rootElement = document.RootElement; Assert.Equal(JsonValueKind.Object, rootElement.ValueKind); JsonProperty property = Assert.Single(rootElement.EnumerateObject()); JsonParserContext context = new JsonParserContext(); return(parser(property.Name, property.Value, context)); } }
public void InvalidJsonReportingJsonInvalidError() { string json = @" { ""$Version"": ""4.01"" "; // missing a } Utf8JsonReader jsonReader = GetJsonReader(json); JsonParserContext context = new JsonParserContext(); CsdlJsonParser.ParseCsdlDocument(ref jsonReader, context); EdmError error = Assert.Single(context.Errors); Assert.Equal(EdmErrorCode.InvalidJson, error.ErrorCode); Assert.Equal("$ LineNumber:0 BytePositionInLine:22 Path:N/A ActualMessage:Expected depth to be zero at the end of the JSON payload." + " There is an open JSON object or array that should be closed. LineNumber: 0 | BytePositionInLine: 22.", error.ErrorMessage); }
/// <summary> /// Parser method which parses the top level Json Object which represents the overall Graph /// </summary> /// <param name="context">Parser Context</param> private void ParseTriplesArray(JsonParserContext context) { try { context.Handler.StartRdf(); //Can we read the overall Graph Object PositionInfo startPos = context.CurrentPosition; if (context.Input.Read()) { if (context.Input.TokenType == JsonToken.StartArray) { if (!context.Input.Read()) { throw Error(context, "Unexpected End of Input encountered, expected the start of a Triple Object/end of the Triples array"); } if (context.Input.TokenType == JsonToken.StartObject) { this.ParseTriples(context); } //Should see an End Array when we get back here if (context.Input.TokenType != JsonToken.EndArray) { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, end of the JSON Array was expected"); } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, start of the JSON Array was expected", startPos); } } else { throw Error(context, "Unexpected End of Input while trying to parse start of the JSON Triple Array", startPos); } context.Handler.EndRdf(true); } catch (RdfParsingTerminatedException) { context.Handler.EndRdf(true); } catch { context.Handler.EndRdf(false); throw; } }
public static void ParseAsObject(this JsonElement element, JsonParserContext context, Action <string, JsonElement> propertyParser) { Debug.Assert(context != null); Debug.Assert(element.ValueKind == JsonValueKind.Object); foreach (var propertyItem in element.EnumerateObject()) { context.EnterScope(propertyItem.Name); propertyParser(propertyItem.Name, propertyItem.Value); context.LeaveScope(propertyItem.Name); } }
private INode TryParseNode(JsonParserContext context, out TripleSegment segment) { if (context.Input.Read()) { if (context.Input.TokenType == JsonToken.PropertyName) { //Determine the Triple Segment switch (context.Input.Value.ToString()) { case "subject": segment = TripleSegment.Subject; break; case "predicate": segment = TripleSegment.Predicate; break; case "object": segment = TripleSegment.Object; break; default: throw Error(context, "Unexpected Property '" + context.Input.Value.ToString() + "' encountered, expected one of 'subject', 'predicate' or 'object'"); } if (context.Input.Read()) { String value = context.Input.Value.ToString(); return(this.TryParseNodeValue(context, value)); } else { throw Error(context, "Unexpected End of Input when a Value for a Node of a Triple was expected"); } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Name for the node of a Triple"); } } else { throw Error(context, "Unexpected End of Input when a Property Value pair for a Node of a Triple was expected"); } }
public void ParseIncludeWorksAsExpected() { string json = @" { ""$Namespace"": ""org.example.display"", ""$Alias"": ""UI"" }"; using (JsonDocument document = JsonDocument.Parse(json)) { JsonElement rootElement = document.RootElement; JsonParserContext context = new JsonParserContext(); CsdlInclude include = CsdlJsonParser.ParseInclude(rootElement, context); Assert.NotNull(include); Assert.Equal("UI", include.Alias); Assert.Equal("org.example.display", include.Namespace); } }
private static CsdlAnnotation ParseAnnotation(string annotation, out JsonParserContext context) { string wrapper = "{" + annotation + "}"; using (JsonDocument document = JsonDocument.Parse(wrapper)) { JsonElement rootElement = document.RootElement; context = new JsonParserContext(); Assert.Equal(JsonValueKind.Object, rootElement.ValueKind); // only one property JsonProperty property = Assert.Single(rootElement.EnumerateObject()); bool ok = AnnotationJsonParser.TryParseCsdlAnnotation(property.Name, property.Value, context, out CsdlAnnotation csdlAnnotation); Assert.True(ok); return(csdlAnnotation); } }
/// <summary> /// Tries parsing the given CSDL-JSON artifact for an IEdmModel. /// </summary> /// <param name="reader">The given JSON reader containing the CSDL artifact.</param> /// <param name="settings">CSDL-JSON reader settings for current parser.</param> /// <param name="model">The model generated by parsing</param> /// <param name="errors">Errors reported while parsing.</param> /// <returns>Success of the parse operation.</returns> public static bool TryParse(ref Utf8JsonReader reader, CsdlJsonReaderSettings settings, out IEdmModel model, out IEnumerable <EdmError> errors) { EdmUtil.CheckArgumentNull(settings, nameof(settings)); model = null; JsonParserContext context = new JsonParserContext(settings, source: null); CsdlModel mainModel = CsdlJsonParser.ParseCsdlDocument(ref reader, context); if (mainModel != null && !context.HasIntolerableError()) { Debug.Assert(mainModel.CsdlVersion != null, "csdlVersion != null"); List <CsdlModel> referencedAstModels = LoadReferencedCsdl(mainModel, context); if (!context.HasIntolerableError()) { CsdlSemanticsModel tmp = new CsdlSemanticsModel(mainModel, new CsdlSemanticsDirectValueAnnotationsManager(), referencedAstModels, settings.IncludeDefaultVocabularies); // add more referenced IEdmModels in addition to the above loaded CsdlModels. if (settings.ReferencedModels != null) { tmp.AddToReferencedModels(settings.ReferencedModels); } model = tmp; model.SetEdmxVersion(mainModel.CsdlVersion); Version edmVersion; if (CsdlConstants.EdmxToEdmVersions.TryGetValue(mainModel.CsdlVersion, out edmVersion)) { model.SetEdmVersion(edmVersion); } } } errors = context.Errors; return(!context.HasIntolerableError()); }
public void ParseIncludeAnnotationsWorksAsExpected() { string json = @" { ""$TermNamespace"": ""org.example.hcm"", ""$Qualifier"": ""Tablet"", ""$TargetNamespace"": ""com.example.Person"" }"; using (JsonDocument document = JsonDocument.Parse(json)) { JsonElement rootElement = document.RootElement; JsonParserContext context = new JsonParserContext(); CsdlIncludeAnnotations includeAnnotations = CsdlJsonParser.ParseIncludeAnnotations(rootElement, context); Assert.NotNull(includeAnnotations); Assert.Equal("org.example.hcm", includeAnnotations.TermNamespace); Assert.Equal("Tablet", includeAnnotations.Qualifier); Assert.Equal("com.example.Person", includeAnnotations.TargetNamespace); } }
/// <summary> /// Internal top level Parse method which parses the Json /// </summary> /// <param name="handler">RDF Handler to use</param> /// <param name="input">Stream to read from</param> private void Parse(IRdfHandler handler, TextReader input) { JsonParserContext context = new JsonParserContext(handler, new CommentIgnoringJsonTextReader(input)); try { context.Handler.StartRdf(); this.ParseGraphObject(context); context.Handler.EndRdf(true); } catch (RdfParsingTerminatedException) { context.Handler.EndRdf(true); //Discard this - it justs means the Handler told us to stop } catch { context.Handler.EndRdf(false); throw; } }
public void ParseIncludeReportUnExpectedMember() { string json = @" { ""$Namespace"": ""org.example.display"", ""$Unknown"": ""UI"" }"; using (JsonDocument document = JsonDocument.Parse(json)) { JsonElement rootElement = document.RootElement; JsonParserContext context = new JsonParserContext(); CsdlInclude include = CsdlJsonParser.ParseInclude(rootElement, context); Assert.NotNull(include); Assert.Equal("org.example.display", include.Namespace); var error = Assert.Single(context.Errors); Assert.Equal(EdmErrorCode.UnexpectedElement, error.ErrorCode); Assert.Equal("$.$Unknown", error.ErrorLocation.ToString()); Assert.Equal("A member '$.$Unknown' with value type 'String' is unexpected.", error.ErrorMessage); } }
/// <summary> /// Parser method which parses Json Objects representing Predicate Object Lists /// </summary> /// <param name="context">Parser Context</param> /// <param name="subj">Subject of Triples which comes from the parent Json Object</param> private void ParsePredicateObjectList(JsonParserContext context, INode subj) { PositionInfo startPos = context.CurrentPosition; if (context.Input.Read()) { if (context.Input.TokenType == JsonToken.StartObject) { context.Input.Read(); while (context.Input.TokenType != JsonToken.EndObject) { //Expect Property Names for Predicates if (context.Input.TokenType == JsonToken.PropertyName) { String predValue = context.Input.Value.ToString(); INode predNode = context.Handler.CreateUriNode(new Uri(predValue)); this.ParseObjectList(context, subj, predNode); } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected a Property Name which represents a Predicate", startPos); } context.Input.Read(); } } else { throw Error(context, "Unexpected Token '" + context.Input.TokenType.ToString() + "' encountered, expected the start of a JSON Object to represent a Predicate Object List", startPos); } } else { throw Error(context, "Unexpected End of Input while trying to parse a Predicate Object List from the JSON", startPos); } }