/// <summary> /// Deserializes the payload using the JsonParser, then converts the resulting clr objects into payload element form /// Throws an TaupoInvalidOperationException if the json does not evaluate successfully. /// </summary> /// <param name="serialized">A raw json payload</param> /// <param name="payloadContext">Additional payload information to aid deserialization</param> /// <returns>A PayloadElement representation of the payload</returns> public ODataPayloadElement DeserializeFromBinary(byte[] serialized, ODataPayloadContext payloadContext) { ExceptionUtilities.CheckArgumentNotNull(serialized, "serialized"); ExceptionUtilities.CheckArgumentNotNull(payloadContext, "payloadContext"); string encodingName = payloadContext.EncodingName; ODataPayloadElement errorPayload = null; if (this.payloadErrorDeserializer.TryDeserializeErrorPayload(serialized, encodingName, out errorPayload)) { return errorPayload; } // Evaluate the given JSON text Encoding encoding = HttpUtilities.GetEncodingOrDefault(encodingName); string payload = encoding.GetString(serialized, 0, serialized.Length); JsonValue jsonData = null; using (StringReader reader = new StringReader(payload)) { JsonTokenizer tokenizer = new JsonTokenizer(reader); JsonParser parser = new JsonParser(tokenizer); jsonData = parser.ParseValue(); } // convert the deserialized JsonValue objects into payload elements return this.payloadConverter.ConvertToPayloadElement(jsonData); }
/// <summary> /// Deserializes given HTTP payload as a json error payload or returns false /// </summary> /// <param name="serialized">The payload that was sent over HTTP</param> /// <param name="encodingName">Optional name of an encoding to use if it is relevant to the current format. May be null if no character-set information was known.</param> /// <param name="errorPayload">Error payload that is found</param> /// <returns>True if it finds and error, false if not</returns> public bool TryDeserializeErrorPayload(byte[] serialized, string encodingName, out ODataPayloadElement errorPayload) { ExceptionUtilities.CheckArgumentNotNull(serialized, "serialized"); errorPayload = null; Encoding encoding = HttpUtilities.GetEncodingOrDefault(encodingName); string payload = encoding.GetString(serialized, 0, serialized.Length); // sample json error // { // “error”: { // “code”: <string> // “message”: { // “lang”: <string>, // “value“: <string> // }, // “innererror”: { // “message”: <string>, // “type”: <string>, // “stacktrace”: <string>, // “internalexception”: { // … another inner error structure … // } // } // } // } string errorName = "\"" + ODataConstants.ErrorElementName + "\":"; int errorElementPos = payload.IndexOf(errorName, StringComparison.Ordinal); // Look in the payload and see if an error exists if (errorElementPos > -1) { ODataErrorPayload topLevelError = new ODataErrorPayload(); errorPayload = topLevelError; ODataInternalExceptionPayload innerError = null; bool inTopLevelMessage = false; bool inError = false; using (StringReader reader = new StringReader(payload.Substring(errorElementPos))) { JsonTokenizer tokenizer = new JsonTokenizer(reader); while (tokenizer.HasMoreTokens()) { if (tokenizer.TokenType == JsonTokenType.String) { string tokenValue = null; if (tokenizer != null) { tokenValue = tokenizer.Value.ToString(); } // don't start processing other properties until we're definitely inside the error itself if (!inError) { inError = tokenValue == ODataConstants.ErrorElementName; } else { if (tokenValue == ODataConstants.InnerErrorElementName) { this.Assert.IsNull(innerError, "Should not find 'innererror' property on inner errors"); topLevelError.InnerError = innerError = new ODataInternalExceptionPayload(); } else if (tokenValue == ODataConstants.InternalExceptionElementName) { this.Assert.IsNotNull(innerError, "Should not find 'internalexception' property on top-level errors"); ExceptionUtilities.Assert(innerError.InternalException == null, "Inner error should have been null"); innerError.InternalException = new ODataInternalExceptionPayload(); innerError = innerError.InternalException; } else if (tokenValue == ODataConstants.MessageElementName) { if (innerError == null) { inTopLevelMessage = true; } else { innerError.Message = this.GetIdentifierValue(tokenizer); } } else if (tokenValue == ODataConstants.ValueElementName) { this.Assert.IsTrue(inTopLevelMessage, "Should not find 'value' property outside top-level message"); this.Assert.IsNull(innerError, "Should not find 'value' property on inner errors"); topLevelError.Message = this.GetIdentifierValue(tokenizer); } else if (tokenValue == ODataConstants.CodeElementName) { this.Assert.IsNull(innerError, "Should not find 'code' property on inner errors"); topLevelError.Code = this.GetIdentifierValue(tokenizer); } else if (tokenValue == ODataConstants.TypeNameElementName) { this.Assert.IsNotNull(innerError, "Should not find 'type' on top-level errors"); innerError.TypeName = this.GetIdentifierValue(tokenizer); } else if (tokenValue == ODataConstants.StackTraceElementName) { this.Assert.IsNotNull(innerError, "Should not find 'stacktrace' on top-level errors"); innerError.StackTrace = this.GetIdentifierValue(tokenizer); } } } else if (tokenizer.TokenType == JsonTokenType.RightCurly) { inTopLevelMessage = false; } tokenizer.GetNextToken(); } } return true; } return false; }
private string GetIdentifierValue(JsonTokenizer tokenizer) { tokenizer.GetNextToken(); ExceptionUtilities.Assert(tokenizer.TokenType == JsonTokenType.Colon, "Error parsing JSON Error: Expected colon token next"); tokenizer.GetNextToken(); ExceptionUtilities.Assert(tokenizer.TokenType == JsonTokenType.String, "Error parsing JSON Error: Expected string token next"); ExceptionUtilities.CheckObjectNotNull(tokenizer.Value, "Expected tokenizer to have a value and not be null"); return tokenizer.Value.ToString(); }
/// <summary> /// Parses the specified text reader content into a <see cref="JsonValue"/> /// </summary> /// <param name="reader">The reader to read.</param> /// <returns>The <see cref="JsonValue"/> read from the reader.</returns> public static JsonValue ParseValue(TextReader reader) { var tokenizer = new JsonTokenizer(reader); var parser = new JsonTextPreservingParser(tokenizer); return parser.ParseValueOrProperty(); }
/// <summary> /// Initializes a new instance of the JsonParser class /// </summary> /// <param name="tokenizer">An instance of <see cref="JsonTokenizer"/></param> public JsonTextPreservingParser(JsonTokenizer tokenizer) { ExceptionUtilities.CheckArgumentNotNull(tokenizer, "tokenizer"); this.tokenizer = tokenizer; }
public override ODataPayloadElement Visit(PrimitiveValue payloadElement) { var rawText = payloadElement.Annotations.OfType<RawTextPayloadElementRepresentationAnnotation>().Select(r => r.Text).SingleOrDefault(); var dataType = payloadElement.Annotations.OfType<DataTypeAnnotation>().Select(d => d.DataType).OfType<PrimitiveDataType>().SingleOrDefault(); if (rawText != null && dataType != null) { using (var reader = new StringReader(rawText)) { var tokenizer = new JsonTokenizer(reader); var parsed = tokenizer.Value; if (tokenizer.TokenType == JsonTokenType.String) { var clrType = dataType.GetFacetValue<PrimitiveClrTypeFacet, Type>(null); if (this.converter.TryConvertFromString((string)parsed, clrType, out parsed)) { return payloadElement.ReplaceWith(new PrimitiveValue(payloadElement.FullTypeName, parsed)); } } } } return base.Visit(payloadElement); }
/// <summary> /// Initializes a new instance of the JsonParser class /// </summary> /// <param name="tokenizer">An instance of <see cref="JsonTokenizer"/></param> public JsonParser(JsonTokenizer tokenizer) { ExceptionUtilities.CheckArgumentNotNull(tokenizer, "tokenizer"); this.tokenizer = tokenizer; }