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'],
);
}
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 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
i using redux tool kit to build react native app and i try to normalize my data like this
const postEntitiy = new schema.Entity('post');
const postAdapter = createEntityAdapter({
selectId: (post) => post._id,
});
const normalized = normalize(response.data, postEntitiy);
this is my resopose.data
Array [
Object {
"__v": 5,
"_id": "6020b367cb94a91c9cd48c34",
"comments": Array [],
"date": "2021-02-08T03:43:35.742Z",
"likes": Array [
Object {
"_id": "60216bd341b3744ce4b13bee",
"user": "601f2d46017c85357800da96",
},
],",
},
]
and this is the error it throw
The entity passed to the `selectId` implementation returned undefined., You should probably provide
your own selectId implementation.,
The entity that was passed:, Object {
"undefined": Object {
"0": Object {
"__v": 5,
"_id": "6020b367cb94a91c9cd48c34",
"comments": Array [],
"date": "2021-02-08T03:43:35.742Z",
"likes": Array [
Object {
"_id": "60216bd341b3744ce4b13bee",
"user": "601f2d46017c85357800da96",
},
],
},
]
As this is written the postAdapter and the normalize are independent of each other. What's happening here is that normalize is attempting the map the data into entities, but it ends up with the key as undefined because it is using the default key of id which has an undefined value. Additionally you have an array of entities rather than just one.
The postAdapter then tries to find the selectId on this data which has already been normalized. But the postAdapter is not looking at a single post object -- it is looking at the nested data created by normalize. It is looking at the data structure Object { "undefined": Object { "0": Object {... from your error. The "undefined": is caused by the bad id attribute and the "0": is because it is an array.
How you do write this correctly kind of depends on what it is that you are trying to do. It's possible that normalize is not really necessary here. It looks like the likes in response.data are already returning a string id for the like and the user instead of the deeply-nested data that the normalizr package is designed to flatten. If you want to use normalize and have it work properly then you need to set the idAttribute on the options argument (docs link).
const postEntity = new schema.Entity('post', {}, {idAttribute: '_id'});
const normalized = data.map( o => normalize(o, postEntity));
idAttribute also accepts a function. You can create a reusable id extractor function that pulls the _id property from any object with {_id: string;}.
const myIdExtractor = (object : {_id: string;}) => object._id;
const postEntity = new schema.Entity('post', {}, {idAttribute: myIdExtractor});
const normalized = data.map( o => normalize(o, postEntity));
That same id extractor function also works with createEntityAdapter.
const postAdapter = createEntityAdapter({
selectId: myIdExtractor,
});
I'm using grpcc, which is based on protobuf.js, to test my grpc service APIs.
My .proto file:
message MyRequest {
string userId = 1;
map<string, string> params = 2;
}
I tried the following json body to send a request:
{userId : "my_user_id" , params: { name: "my_name"}}
{userId : "my_user_id" , params: [{"name":"my_name"}] }
But this gives the following error:
Error: Illegal value for Message.Field....MyRequest.params of type string: object (expected ProtoBuf.Map or raw object for map field)
How to correctly represent a protobuf map as a json?
The proper json body would be the following:
{ "userId": "my_user_id", "params": { "name": "my_name" } }
What you've tried doing is an array of maps, which doesn't really mean anything in the context of protobuf. A map<string, string> is exactly the description of a json object, so more than one value would be represented the following way:
{ "params": { "key1": "value1", "key2": "value2" } }
No need for an array.
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.