internal static PreprocessResult PreprocessRequest( object content, HttpRequestMessage request, JsonApiConfiguration config) { var jsonApi = new JsonApiSerializer(); jsonApi.JsonConverters.AddRange(config.JsonConverters); PrepareQueryContext(jsonApi, request, config); ApiResource resource = null; if (request.Properties.ContainsKey(Constants.PropertyNames.ResourceDescriptor)) { resource = (ApiResource)request.Properties[Constants.PropertyNames.ResourceDescriptor]; } else if (content != null && !(content is HttpError)) { content = new JsonApiException( ErrorType.Server, "You must add a [ReturnsResourceAttribute] to action methods.") { HelpLink = "https://github.com/joukevandermaas/saule/wiki" }; } PrepareUrlPathBuilder(jsonApi, request, config); return(jsonApi.PreprocessContent(content, resource, request.RequestUri)); }
/// <summary> /// Attempt to patch the given entity. /// </summary> /// <param name="entity">The entity to apply the patch to.</param> /// <param name="contractResolver">The contract resolver to use.</param> /// <returns>true if the entity could be patched, false if not.</returns> public bool TryPatch(T entity, IContractResolver contractResolver) { try { var jsonObject = _jsonValue["data"] as JsonObject; var typeAttribute = jsonObject?["type"]; if (typeAttribute == null) { return(false); } IContract contract; if (contractResolver.TryResolve(((JsonString)typeAttribute).Value, out contract) == false) { return(false); } var serializer = new JsonApiSerializer(contractResolver, _fieldNamingStratgey); serializer.DeserializeEntity(contract, jsonObject, entity); return(true); } // ReSharper disable once EmptyGeneralCatchClause catch { } return(false); }
private static void PrepareQueryContext( JsonApiSerializer jsonApiSerializer, HttpRequestMessage request, JsonApiConfiguration config) { if (!request.Properties.ContainsKey(Constants.PropertyNames.QueryContext)) { return; } var queryContext = (QueryContext)request.Properties[Constants.PropertyNames.QueryContext]; if (queryContext.Filtering != null) { queryContext.Filtering.QueryFilters = config.QueryFilterExpressions; } PaginationContext pagination = queryContext.Pagination; if (pagination != null) { if (!pagination.PageSizeLimit.HasValue) { pagination.PageSizeLimit = config.PaginationConfig.DefaultPageSizeLimit; } if (!pagination.PerPage.HasValue) { pagination.PerPage = config.PaginationConfig.DefaultPageSize; } } jsonApiSerializer.QueryContext = queryContext; }
private static void PrepareUrlPathBuilder( JsonApiSerializer jsonApiSerializer, HttpRequestMessage request, JsonApiConfiguration config, ApiResource resource) { var result = config.UrlPathBuilder; if (resource == null) { result = result ?? new DefaultUrlPathBuilder(); } else if (!request.Properties.ContainsKey("MS_RequestContext")) { result = result ?? new DefaultUrlPathBuilder(); } else { var routeTemplate = (request.Properties["MS_RequestContext"] as HttpRequestContext) ?.RouteData.Route.RouteTemplate; result = result ?? new DefaultUrlPathBuilder( routeTemplate, resource); } jsonApiSerializer.UrlPathBuilder = result; }
/// <summary> /// Deserialize an object. /// </summary> /// <param name="type">The type of the object to deserialize.</param> /// <param name="jsonValue">The JSON value that represents the object to deserialize.</param> protected override object DeserializeValue(Type type, JsonValue jsonValue) { var jsonObject = jsonValue as JsonObject; if (jsonObject == null) { throw new HypermediaWebApiException("The top level JSON value must be an Object."); } var serializer = new JsonApiSerializer( new JsonApiSerializerOptions { ContractResolver = ContractResolver, FieldNamingStrategy = FieldNamingStrategy }); if (TypeHelper.IsEnumerable(type)) { var collection = TypeHelper.CreateListInstance(type); foreach (var item in serializer.DeserializeMany(jsonObject)) { collection.Add(item); } return(collection); } return(serializer.Deserialize(jsonObject)); }
public void Can_Serialize_Complex_Types() { // arrange var contextGraphBuilder = new ContextGraphBuilder(); contextGraphBuilder.AddResource <TestResource>("test-resource"); var contextGraph = contextGraphBuilder.Build(); var jsonApiContextMock = new Mock <IJsonApiContext>(); jsonApiContextMock.SetupAllProperties(); jsonApiContextMock.Setup(m => m.ContextGraph).Returns(contextGraph); jsonApiContextMock.Setup(m => m.Options).Returns(new JsonApiOptions()); jsonApiContextMock.Setup(m => m.RequestEntity) .Returns(contextGraph.GetContextEntity("test-resource")); jsonApiContextMock.Setup(m => m.MetaBuilder).Returns(new MetaBuilder()); jsonApiContextMock.Setup(m => m.PageManager).Returns(new PageManager()); var documentBuilder = new DocumentBuilder(jsonApiContextMock.Object); var serializer = new JsonApiSerializer(jsonApiContextMock.Object, documentBuilder); var resource = new TestResource { ComplexMember = new ComplexType { CompoundName = "testname" } }; // act var result = serializer.Serialize(resource); // assert Assert.NotNull(result); Assert.Equal("{\"data\":{\"attributes\":{\"complex-member\":{\"compound-name\":\"testname\"}},\"type\":\"test-resource\",\"id\":\"\"}}", result); }
/// <summary> /// Attempt to patch the given entity. /// </summary> /// <param name="entity">The entity to apply the patch to.</param> /// <param name="contractResolver">The contract resolver to use.</param> /// <returns>true if the entity could be patched, false if not.</returns> public bool TryPatch(T entity, IContractResolver contractResolver) { try { var jsonObject = _jsonValue["data"] as JsonObject; if (TryResolveContact(contractResolver, jsonObject, out var contract) == false) { return(false); } var serializer = new JsonApiSerializer( new JsonApiSerializerOptions(new ContractResolver(contract)) { FieldNamingStrategy = _fieldNamingStratgey }); serializer.DeserializeEntity(contract, jsonObject, entity); return(true); } // ReSharper disable once EmptyGeneralCatchClause catch { } return(false); }
internal static PreprocessResult PreprocessRequest( object content, HttpRequestMessage request, JsonApiConfiguration config) { var jsonApi = new JsonApiSerializer(); jsonApi.JsonConverters.AddRange(config.JsonConverters); PrepareQueryContext(jsonApi, request, config); ApiResource resource = null; if (request.Properties.ContainsKey(Constants.RequestPropertyName)) { resource = (ApiResource)request.Properties[Constants.RequestPropertyName]; } else if (content != null && !(content is HttpError)) { content = new JsonApiException( ErrorType.Server, "You must add a [ReturnsResourceAttribute] to action methods.") { HelpLink = "https://github.com/joukevandermaas/saule/wiki" }; } PrepareUrlPathBuilder(jsonApi, request, config); return jsonApi.PreprocessContent(content, resource, request.RequestUri); }
public void Can_Return_Custom_Error_Types() { // arrange var error = new CustomError(507, "title", "detail", "custom"); var errorCollection = new ErrorCollection(); errorCollection.Add(error); var expectedJson = JsonConvert.SerializeObject(new { errors = new dynamic[] { new { myCustomProperty = "custom", title = "title", detail = "detail", status = "507" } } }); // act var result = new JsonApiSerializer(null, null, null) .Serialize(errorCollection); // assert Assert.Equal(expectedJson, result); }
/// <summary> /// Read the content as a JSONAPI response object. /// </summary> /// <param name="httpContent">The HTTP content to read the JSONAPI response from.</param> /// <param name="serializerOptions">The options to use for the serializer.</param> /// <param name="cache">The entity cache to use for resolving existing instances in the object graph.</param> /// <returns>The JSONAPI response element that was read from the stream in the HTTP content.</returns> public static Task <TEntity> ReadAsJsonApiAsync <TEntity>( this HttpContent httpContent, JsonApiSerializerOptions serializerOptions, IJsonApiEntityCache cache) { var serializer = new JsonApiSerializer(serializerOptions); return(httpContent.ReadAsJsonApiAsync <TEntity>(serializer, cache)); }
/// <summary> /// Read the content as a JSONAPI response object. /// </summary> /// <param name="httpContent">The HTTP content to read the JSONAPI response from.</param> /// <param name="contractResolver">The resource contract resolver use to resolve types during deserialization.</param> /// <param name="cache">The entity cache to use for resolving existing instances in the object graph.</param> /// <returns>The JSONAPI response element that was read from the stream in the HTTP content.</returns> public static Task <TEntity> ReadAsJsonApiAsync <TEntity>( this HttpContent httpContent, IContractResolver contractResolver, IJsonApiEntityCache cache) { var serializer = new JsonApiSerializer(contractResolver, new DasherizedFieldNamingStrategy()); return(httpContent.ReadAsJsonApiAsync <TEntity>(serializer, cache)); }
public void WorksOnHttpErrors() { var target = new JsonApiSerializer <PersonResource>(); var result = target.Serialize(new HttpError(), DefaultUrl); _output.WriteLine(result.ToString()); Assert.Null(result["data"]); Assert.NotNull(result["errors"]); }
public void Gives() { var target = new JsonApiSerializer <PersonResource>(); var initialPerson = Get.Person(); var personJson = target.Serialize(initialPerson, DefaultUrl); var dsPerson = (Person)target.Deserialize(personJson, typeof(Person)); Assert.Equal(initialPerson.FirstName, dsPerson.FirstName); }
/// <summary> /// Read the content as a JSONAPI response object. /// </summary> /// <param name="httpContent">The HTTP content to read the JSONAPI response from.</param> /// <param name="contractResolver">The resource contract resolver use to resolve types during deserialization.</param> /// <param name="cache">The entity cache to use for resolving existing instances in the object graph.</param> /// <returns>The JSONAPI response element that was read from the stream in the HTTP content.</returns> public static Task <List <TEntity> > ReadAsJsonApiManyAsync <TEntity>(this HttpContent httpContent, IContractResolver contractResolver, IJsonApiEntityCache cache) { var serializer = new JsonApiSerializer( new JsonApiSerializerOptions(contractResolver) { FieldNamingStrategy = DasherizedFieldNamingStrategy.Instance }); return(httpContent.ReadAsJsonApiManyAsync <TEntity>(serializer, cache)); }
/// <summary> /// Serialize the value into an JSON AST. /// </summary> /// <param name="type">The type to serialize from.</param> /// <param name="value">The value to serialize.</param> /// <returns>The JSON object that represents the serialized value.</returns> protected override JsonValue SerializeValue(Type type, object value) { var serializer = new JsonApiSerializer(ContractResolver, _fieldNamingStratgey); if (TypeHelper.IsEnumerable(type)) { return(serializer.SerializeMany((IEnumerable)value)); } return(serializer.SerializeEntity(value)); }
/// <summary> /// Serialize the value into an JSON AST. /// </summary> /// <param name="type">The type to serialize from.</param> /// <param name="value">The value to serialize.</param> /// <returns>The JSON object that represents the serialized value.</returns> JsonValue SerializeContract(Type type, object value) { var serializer = new JsonApiSerializer(ContractResolver, FieldNamingStrategy); if (TypeHelper.IsEnumerable(type)) { return(serializer.SerializeMany((IEnumerable)value)); } return(serializer.SerializeEntity(value)); }
public void CanDeserializeNullBelongsRelationship() { // arrange var serializer = new JsonApiSerializer(HypermediaSampleClient.CreateResolver()); // act var resource = (PostResource)serializer.Deserialize(JsonContent.GetObject(nameof(CanDeserializeNullBelongsRelationship))); // assert Assert.Equal(2, resource.Id); Assert.Null(resource.OwnerUser); }
public void UsesConverters() { var target = new JsonApiSerializer <CompanyResource>(); var company = Get.Company(); target.JsonConverters.Add(new StringEnumConverter()); var result = target.Serialize(company, DefaultUrl); _output.WriteLine(result.ToString()); Assert.Equal(company.Location.ToString(), result["data"]["attributes"].Value <string>("location")); }
public void DoesNotIncludeNullData() { var target = new JsonApiSerializer <PersonResource>(); var model = new Person() { Identifier = "Id", Job = null }; var result = target.Serialize(model, DefaultUrl); Assert.Null(result["data"]["relationships"]["job"]["data"]); }
public void CanDeserialize() { // arrange var serializer = new JsonApiSerializer(HypermediaSampleClient.CreateResolver()); // act var resource = (PostResource)serializer.Deserialize(JsonContent.GetObject(nameof(CanDeserialize))); // assert Assert.Equal(2, resource.Id); Assert.Equal("Did the Greeks build temples for all of the children of Cronus?", resource.Title); Assert.Equal("kuwaly", resource.OwnerUser.DisplayName); }
public void ReturnEmptyModelForUnknownFieldsetExpressions() { var target = new JsonApiSerializer <CompanyResource> { AllowQuery = true }; var companies = Get.Companies(1).ToList(); var result = target.Serialize(companies, new Uri(DefaultUrl, "?fields[corporation]=Notafield")); _output.WriteLine(result.ToString()); Assert.False(((JToken)result["data"][0]["attributes"]).HasValues); }
private string GetResponseBody(object responseObject, IJsonApiContext jsonApiContext, ILogger logger) { if (responseObject == null) { return(GetNullDataResponse()); } if (responseObject.GetType() == typeof(Error) || jsonApiContext.RequestEntity == null) { return(GetErrorJson(responseObject, logger)); } return(JsonApiSerializer.Serialize(responseObject, jsonApiContext)); }
public JObject Serialize(JsonSerializer serializer) { serializer.ContractResolver = new JsonApiContractResolver(_propertyNameConverter); _serializer = serializer; _sourceSerializer = JsonApiSerializer.GetJsonSerializer(_serializer.Converters); _sourceSerializer.ContractResolver = new SourceContractResolver(_propertyNameConverter, _resource); if (_value == null) { return(SerializeNull()); } var graph = new ResourceGraph(_value, _resource, _includedGraphPaths); var dataSection = SerializeData(graph); var includesSection = SerializeIncludes(graph); var metaSection = SerializeMetadata(); var result = new JObject { ["data"] = dataSection }; var isCollection = _value.IsCollectionType(); string id = null; if (!isCollection) { id = dataSection["id"]?.ToString(); } var links = CreateTopLevelLinks(dataSection is JArray ? dataSection.Count() : 0, id); if (links.HasValues) { result.Add("links", links); } if (includesSection != null && includesSection.Count > 0) { result["included"] = includesSection; } if (metaSection != null) { result["meta"] = metaSection; } return(result); }
public void CanDeserializeNullHasManyRelationship() { // arrange var serializer = new JsonApiSerializer(new JsonApiSerializerOptions { ContractResolver = HypermediaSampleClient.CreateResolver() }); // act var resource = (PostResource)serializer.Deserialize(JsonContent.GetObject(nameof(CanDeserializeNullHasManyRelationship))); // assert Assert.Equal(2, resource.Id); Assert.Null(resource.Comments); }
public void UsesQueryFieldsetExpressions() { var target = new JsonApiSerializer <CompanyResource> { AllowQuery = true }; var companies = Get.Companies(1).ToList(); var result = target.Serialize(companies, new Uri(DefaultUrl, "?fields[corporation]=Name,Location")); _output.WriteLine(result.ToString()); Assert.NotNull(result["data"][0]["attributes"]["name"]); Assert.NotNull(result["data"][0]["attributes"]["location"]); Assert.Null(result["data"][0]["attributes"]["number-of-employees"]); }
public void UsesQueryFieldsetExpressionsOnRelationships() { var target = new JsonApiSerializer <PersonResource> { AllowQuery = true }; var people = Get.People(1).ToList(); var result = target.Serialize(people, new Uri(DefaultUrl, "?fields[person]=Job")); _output.WriteLine(result.ToString()); var relationships = result["data"][0]["relationships"]; Assert.Null(relationships["family-members"]); Assert.NotNull(relationships["job"]); }
public void GivesUsefulErrorForEnumerable() { var target = new JsonApiSerializer <PersonResource> { AllowQuery = true }; var people = Get.People(100); var result = target.Serialize(people, new Uri(DefaultUrl, "?sort=fail-me")); _output.WriteLine(result.ToString()); var error = result["errors"][0]; Assert.Equal("Attribute 'fail-me' not found.", error["title"].Value <string>()); }
public void UsesUrlBuilder() { var target = new JsonApiSerializer <PersonResource> { UrlPathBuilder = new CanonicalUrlPathBuilder() }; var result = target.Serialize(Get.Person(), DefaultUrl); _output.WriteLine(result.ToString()); var related = result["data"]["relationships"]["job"]["links"]["related"].Value <Uri>() .AbsolutePath; Assert.Equal("/corporations/456/", related); }
public void PropertyInteraction() { var target = new JsonApiSerializer <PersonResource> { ItemsPerPage = 2, Paginate = false }; var people = Get.People(5); var result = target.Serialize(people, DefaultUrl); _output.WriteLine(result.ToString()); Assert.Equal(5, result["data"].Count()); Assert.Null(result["links"]["next"]); Assert.Null(result["links"]["first"]); Assert.NotNull(result["links"]["self"]); }
public void AppliesPagination() { var target = new JsonApiSerializer <PersonResource> { ItemsPerPage = 5, Paginate = true }; var people = Get.People(20).AsQueryable(); var result = target.Serialize(people, DefaultUrl); _output.WriteLine(result.ToString()); Assert.Equal(5, result["data"].Count()); Assert.NotNull(result["links"]["next"]); Assert.NotNull(result["links"]["first"]); Assert.Null(result["links"]["prev"]); }
public void AppliesFilters() { var target = new JsonApiSerializer <CompanyResource> { AllowQuery = true }; var companies = Get.Companies(100).ToList().AsQueryable(); var result = target.Serialize(companies, new Uri(DefaultUrl, "?filter[location]=1")); _output.WriteLine(result.ToString()); var filtered = ((JArray)result["data"]).ToList(); var expected = companies.Where(x => x.Location == LocationType.National).ToList(); Assert.Equal(expected.Count, filtered.Count); }
/// <summary> /// Deserialize an object. /// </summary> /// <param name="type">The type of the object to deserialize.</param> /// <param name="jsonValue">The JSON value that represents the object to deserialize.</param> protected override object DeserializeValue(Type type, JsonValue jsonValue) { var jsonObject = jsonValue as JsonObject; if (jsonObject == null) { throw new HypermediaWebApiException("The top level JSON value must be an Object."); } var serializer = new JsonApiSerializer(ContractResolver, _fieldNamingStratgey); if (TypeHelper.IsEnumerable(type)) { return(serializer.DeserializeMany(jsonObject)); } return(serializer.DeserializeEntity(jsonObject)); }
public void when_serializing() { // Given JsonConvert.DefaultSettings = GetJsonSerializerSettings; var data = new Thing { Id = 5, SomeString = "some string value", SomeGuid = new Guid("77f8195e-ac2e-4c5f-9d0a-f7663ca24435"), NullValue = default(Uri), Bert = new Bert { Id = 45, Banaan = "fiets" }, Ernie = new Ernie { Banaan = "peer", Apple = "fiets" }, Fietsen = new [] { new Fiets { Id = 6, Naam = "batavia" }, new Fiets { Id = 7, Naam = "gazelle" }, new Fiets { Id = 8, Naam = "canondale" } } }; string expected = "{\"data\":{\"type\":\"things\",\"id\":\"5\",\"attributes\":{\"some-string\":\"some string value\",\"some-guid\":\"77f8195e-ac2e-4c5f-9d0a-f7663ca24435\",\"null-value\":null,\"ernie\":{\"banaan\":\"peer\",\"apple\":\"fiets\"}},\"relationships\":{\"bert\":{\"data\":{\"type\":\"berts\",\"id\":\"45\"}},\"fietsen\":{\"data\":[{\"type\":\"fiets\",\"id\":\"6\"},{\"type\":\"fiets\",\"id\":\"7\"},{\"type\":\"fiets\",\"id\":\"8\"}]}}}}"; // When string actual; using (var stream = new MemoryStream()) { ISerializer sut = new JsonApiSerializer(); sut.Serialize("application/vnd.api+json", data, stream); actual = Encoding.UTF8.GetString(stream.ToArray()); } // Then Assert.Equal(expected, actual); }
private static void PrepareUrlPathBuilder( JsonApiSerializer jsonApiSerializer, HttpRequestMessage request, JsonApiConfiguration config) { if (config.UrlPathBuilder != null) { jsonApiSerializer.UrlPathBuilder = config.UrlPathBuilder; } else if (!request.Properties.ContainsKey(Constants.WebApiRequestContextPropertyName)) { jsonApiSerializer.UrlPathBuilder = new DefaultUrlPathBuilder(); } else { var requestContext = request.Properties[Constants.WebApiRequestContextPropertyName] as HttpRequestContext; var routeTemplate = requestContext?.RouteData.Route.RouteTemplate; var virtualPathRoot = requestContext?.VirtualPathRoot ?? "/"; jsonApiSerializer.UrlPathBuilder = new DefaultUrlPathBuilder( virtualPathRoot, routeTemplate); } }
/// <summary> /// Serialize the value into an JSON AST. /// </summary> /// <param name="type">The type to serialize from.</param> /// <param name="value">The value to serialize.</param> /// <returns>The JSON object that represents the serialized value.</returns> protected override JsonValue SerializeValue(Type type, object value) { var serializer = new JsonApiSerializer(ContractResolver, _fieldNamingStratgey); if (TypeHelper.IsEnumerable(type)) { return serializer.SerializeMany((IEnumerable)value); } return serializer.SerializeEntity(value); }
private static void PrepareQueryContext( JsonApiSerializer jsonApiSerializer, HttpRequestMessage request, JsonApiConfiguration config) { if (!request.Properties.ContainsKey(Constants.QueryContextPropertyName)) { return; } var queryContext = (QueryContext)request.Properties[Constants.QueryContextPropertyName]; if (queryContext.Filtering != null) { queryContext.Filtering.QueryFilters = config.QueryFilterExpressions; } jsonApiSerializer.QueryContext = queryContext; }
/// <summary> /// Deserialize an object. /// </summary> /// <param name="type">The type of the object to deserialize.</param> /// <param name="jsonValue">The JSON value that represents the object to deserialize.</param> protected override object DeserializeValue(Type type, JsonValue jsonValue) { var jsonObject = jsonValue as JsonObject; if (jsonObject == null) { throw new HypermediaWebApiException("The top level JSON value must be an Object."); } var serializer = new JsonApiSerializer(ContractResolver, _fieldNamingStratgey); if (TypeHelper.IsEnumerable(type)) { return serializer.DeserializeMany(jsonObject); } return serializer.DeserializeEntity(jsonObject); }