I use ASP.NET Core 3.1
I want my API to return some data which I format as JSON.
For some reason one sub-object that I want to return is a class instance, with properties formatted as UPPERCASE_SNAKE_CASE.
I expect my response to give me data formatted like this :
{
"user": {
"USER_ID": 1,
"USER_CODE": "xxx",
"EMAIL": "myemail#domain.com"
}
}
What I get instead is that some characters before the underscore char are in lowercase :
{
"user": {
"useR_ID": 1,
"useR_CODE": "xxx",
"email": "myemail#domain.com"
}
}
In my Startup.cs file I use the following to format :
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson();
...
}
I tried to add this line I read on other posts :
services.AddControllersWithViews().AddJsonOptions(opts => opts.JsonSerializerOptions.PropertyNamingPolicy = null);
Which didnt change anything.
I don't want all my keys to change into UPPERCASE_SNAKE_CASE, because I am using camelCase, but I want the App to follow how the Key is written in code. When I use a debugger, keys are displayed as I want them to be, it's only in the client part (Angular or Postman) that the keys are messed up.
Have you tried adding [JsonProperty("USER_ID")] style attributes to your class properties? –
DavidG
Mar 2 at 11:43
Related
Odata controllers in my project returns jsons with casing as it is in class so PascalCase.
I want to make them return json with camelCase props.
Controllers which don't use OData returns camelCase jsons by default.
To configure Odata I'm using IMvcBuilder.AddOData() method (extension method from Microsoft.AspNetCore.OData). All my OData controllers inherits from Microsoft.AspNetCore.OData.Rounting.Controllers.ODataController and methods have [EnableQuery] attribute
I guess I should chain AddJsonOptions method after that, but don't know what to pass there. Internet says it should be opt => opt.SerializerSettings.ContractResolver = new DefaultContractResolver(), but opt here is JsonOptions and doesn't have SerializerSettings property.
Edit: Chaining .AddJsonOptions(opt => opt.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase after AddOData doesn't help.
Edit2: Adding [JsonProperty] attributes on model properties also doesn't help.
Edit3: I try to add custom ODataSerializerProvider by register it in 3rd argument of AddRouteComponents, but constructor isn't hit neither at app start nor endpoint call.
Short answer: Call builder.EnableLowerCamelCase()
private static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<User>("User");
// => Add EnableLowerCamelCase here to resolve problem
builder.EnableLowerCamelCase();
return builder.GetEdmModel();
}
Another way answered before is remove AddRouteComponents() call. But this will make Odata only return array data only. For example:
{
"#odata.context": "https://localhost:5001/odata/$metadata#questions",
"#odata.count": 30,
"value": [
{
"name": "name 1"
},
{
"name": "name 2"
},
....
]
}
To return only array data, and remove another properties:
[
{
"name": "name 1"
},
{
"name": "name 2"
},
....
]
The problem was that I was using AddRouteComponents method and custom Edm model. Without it AddJsonObject chained method works. Described here: https://github.com/OData/AspNetCoreOData/blob/main/docs/camel_case_scenarios.md
I'm using a schema interceptor to configure my schema. It's a multi-tenant application, so I build the schema according to the tenant's configuration. I'm mapping that configuration to SDL language (schema-first approach) and then I add it to the schema builder (schemaBuilder.AddDocumentFromString(...)).
As said on the documentation (here), "Schema-first does currently not support filtering!". But that is the only approach I can use right now, so I'm trying to find a workaround.
What I've tried:
Manually create the input filter types and add the filtering to the server (something like this):
...
schemaBuilder.AddDocumentFromString(#"
type Query {
persons(where: PersonFilterInput): [Person]
}
input PersonFilterInput {
and: [PersonFilterInput!]
or: [PersonFilterInput!]
name: StringOperationFilterInput
}
input StringOperationFilterInput {
and: [StringOperationFilterInput!]
or: [StringOperationFilterInput!]
eq: String
neq: String
contains: String
ncontains: String
in: [String]
nin: [String]
startsWith: String
nstartsWith: String
endsWith: String
nendsWith: String
}
}
type Person {
name: String
}");
...
//add resolvers
...
And on the server configuration:
services
.AddGraphQLServer()
.TryAddSchemaInterceptor<TenantSchemaInterceptor>()
.AddFiltering();
However, this is not enough because the filters aren't being applied.
Query:
{
persons (where: { name: {eq: "Joao" }}){
name
}
}
Results:
{
"data": {
"persons": [
{
"name": "Joao"
},
{
"name": "Liliana"
}
]
}
}
Is there anything I can do to workaround this problem?
Thank you people
Filter support for schema-first is coming with version 12. You then do not even have to specify everything since we will provide schema building directives.
type Query {
persons: [Person] #filtering
}
type Person {
name: String
}
you also will be able to control which filter operations can be provided. We have the first preview coming up this week.
I'm trying to follow this tutorial to enable push notifications in my PWA. According to the tutorial, I should get a pushSubscription object like this:
{
"endpoint": "https://fcm.googleapis.com/fcm/send/cbx2QC6AGbY:APA91bEjTzUxaBU7j-YN7ReiXV-MD-bmk2pGsp9ZVq4Jj0yuBOhFRrUS9pjz5FMnIvUenVqNpALTh5Hng7HRQpcUNQMFblTLTF7aw-yu1dGqhBOJ-U3IBfnw3hz9hq-TJ4K5f9fHLvjY",
"expirationTime": null,
"keys": {
"p256dh": "BOXYnlKnMkzlMc6xlIjD8OmqVh-YqswZdut2M7zoAspl1UkFeQgSLYZ7eKqKcx6xMsGK7aAguQbcG9FMmlDrDIA=",
"auth": "if-YFywyb4g-bFB1hO9WMw=="
}
}
However when I inspect my subscription object I get something in the form of
{
"endpoint": "https://fcm.googleapis.com/fcm/send/cbx2QC6AGbY:APA91bEjTzUxaBU7j-YN7ReiXV-MD-bmk2pGsp9ZVq4Jj0yuBOhFRrUS9pjz5FMnIvUenVqNpALTh5Hng7HRQpcUNQMFblTLTF7aw-yu1dGqhBOJ-U3IBfnw3hz9hq-TJ4K5f9fHLvjY",
"expirationTime": null,
"options": {
"applicationServerKey": ArrayBuffer(65),
"userVisibleOnly": true
}
}
note that I do not get the keys object and instead get an options object.
Have the properties of the pushSubscription object changed? If I use this to send notifications, will it still work?
When saving my pushSubscription object with Mongoose, I used keys instead of options
If I then inspect the object in my db (on MLab in my case) it looks like
{
"endpoint": "https://fcm.googleapis.com/fcm/send/cbx2QC6AGbY:APA91bEjTzUxaBU7j-YN7ReiXV-MD-bmk2pGsp9ZVq4Jj0yuBOhFRrUS9pjz5FMnIvUenVqNpALTh5Hng7HRQpcUNQMFblTLTF7aw-yu1dGqhBOJ-U3IBfnw3hz9hq-TJ4K5f9fHLvjY",
"expirationTime": null,
"keys": {
"p256dh": "BOXYnlKnMkzlMc6xlIjD8OmqVh-YqswZdut2M7zoAspl1UkFeQgSLYZ7eKqKcx6xMsGK7aAguQbcG9FMmlDrDIA=",
"auth": "if-YFywyb4g-bFB1hO9WMw=="
}
}
I guess that the object in my console is visualized differently, thus showing me the options parameter instead of keys.
I have implemented api_platform in my symfony 4 project, the problem is that I have to use the paths provided by the Rest api to fetch data using graphql like this
{
user(id:"api/users/1")
{
id
}
}
rather than
{
user(id:1){
id
}
}
Went through the documentation and didn't find a solution for this. Using plain api paths in graph api isn't really worth moving to graphql. Any help.
libraries like Prisma Binding allows you to query GraphQL using APIs
example on fetch user with ID of 1:
const query = `
query ($userId: ID!){
user(id: $userId) {
id
name
}
}
`
const variables = { userId: '1' }
prisma.request(query, variables).then(result => console.log(result))
// {"data": { "user": { "id": "1", "name": "Sarah" } } }
From here, we can write custom wrappers to translate the REST endpoints to corresponding queries
You can handle that in the resolver function, so you will receive a string param in the PHP resolver function instead of int(id).
check this example: https://github.com/khaledalam/simple-system-with-graphql-react-php
I'm attempting to build off of Mike Jansen's JIRA REST Client, and I'm trying to pull in JIRA version information. I'm new to JSON, so I'm not sure if it's just a formatting issue or what.
When debugging, I have the following token:
{[
{
"self": "https://<company>.atlassian.net/rest/api/2/version/10101",
"id": "10101",
"name": "2012.3",
"archived": false,
"released": false,
"releaseDate": "2012-10-08"
},
{
"self": "https://<company>.atlassian.net/rest/api/2/version/10200",
"id": "10200",
"name": "2012.4",
"archived": false,
"released": false
}
]}
and the following line of code
token.Children().Values<T>()
is throwing the following error
Cannot cast Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JToken
while trying to convert the two version tokens into the corresponding JiraVersion class:
using System;
namespace JiraRestClient
{
public class JiraVersion : JiraObjectBase, IJiraVersion
{
public JiraVersion(IJiraRestResponse jiraResponse) : base(jiraResponse) { }
public string Id { get { return Get<string>("Id", "id"); } }
public string Name { get { return Get<string>("Name", "name"); } }
}
}
Can somebody help me out?
Those of you familiar with JSON may have noticed quickly that it was, in fact, a problem with the formatting (the extra curly brackets enclosing the array). Like I said, I'm new to JSON, but the end result of my research is that the JsonWrapper.TryGetPath(...) method attempts to traverse the JObject tree and does not produce correctly formatted JSON when what's being retrieved is an array.
My solution was to simplify things by removing JSON.Net from the solution and depending only on RestSharp (just because it makes it so easy to make requests) and the System.Web.Script.Serialization.JavaScriptSerializer().Deserialize(response.Content) approach.