Cannot cast Newtonsoft.Json.Linq.JProperty to Newtonsoft.Json.Linq.JToken - json.net

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.

Related

ASP NET Core .NET 6 and OData - how to return lowercase json

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

ASP.NET API Key's case is messed up

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

Using hotchocolate's filters with schema first approach

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.

How to create a complex class from a json request

I have two different json that I want to cast in a single class "Response".
The first json gives me something like:
[
{
"id": 1,
"name": "asd",
"objects": [
"id" : asd
...
]
}]
and the other something like:
{
id : 2
name : "asd"
}
The class in which I'm trying to put them is
class Response {
String name;
int id;
Objects object;
}
As you can see, the first one gives me back an array of elements, while the second not. I was trying with the factory method, but then I got stuck. So, is what I want to do possibile, or it's better to do in another way?
Take a look at Serializing JSON inside model classes.
factory classes are a good start (I'm not sure what Objects is supposed to be in your example, your JSON is not valid):
factory Response.fromJson(Map<String, dynamic> json) {
return Response(
id: json['id'],
name: json['name'],
object: json['object'] == null ? null : Objects.fromJson(json['object'],
);
}

FOSRestBundle serializer results in too much queries

I use FOSrestbundle in my API to get my objects as a JSON.
So my controller look like that:
public function getArticleAction($id)
{
$article = $this->getDoctrine()
->getRepository('ApiBundle:Article')
->find($id);
return $this->handleView($this->view($article));
}
And my issue is that an article contains comments, added by users so my json looks like that:
{
"title": "My Article",
"comments": [
{
"content": "my first comment",
"added_by": {
"username": "John"
}
},
{
"content": "my second comment",
"added_by": {
"username": "Smith"
}
}
]
}
and when I render it, there is too many queries, for each comment there is a query to get user informations.
Do I have to get my article object with a querybuilder and lot of join (because it is just an example but I have a lot more relations) to get all the informations in one query or is there an other trick to avoid it ?
You should use EAGER loading for added_by relation while querying your data using Doctrine. This way you will query all data you need for serialization at once.

Resources