Convert Swagger to C# object [duplicate] - c#

This question already has answers here:
How do deserialize JSON with non-standard (and varying) property names (in .NET)
(3 answers)
Closed 5 years ago.
Is there an easy way to convert Json string to C# object?
I have a swagger file in json format and need to make it to C# object
{
"swagger": "2.0",
"info": {
"version": "Profiles",
"title": "Profiles"
},
"paths": {
"/api/Profiles/Get": {
"get": {
"tags": [ "Profiles"],
"operationId": "Profiles_GetById",
"consumes": [],
"produces": [],
"parameters": [{ "name": "id"}]
}
},
"/api/Profiles": {
"get": {
"tags": [
"Profiles"
],
"operationId": "Profiles_GetBySubscriptionid",
"consumes": [],
"produces": [],
"parameters": [{ "name": "subscriptionId"}]
}
}
},
"definitions": {}
}
So the problem that I am facing right now is that I have no idea how to convert paths to properties of my C# object. Specifically, I have no clue how I define a C# object properties for "/api/Profiles/Get", or "/api/Profiles".
public class SwaggerObject
{
[JsonProperty("paths")]
public SwaggerPath Paths { get; set;}
}
public class SwaggerPath {
...
}

If you have a valid swagger definition, you can use AutoRest to generate a client for you. The auto-generated client includes models for all of the types you define in your swagger document.
You can then call Newtonsoft.Json.JsonConvert.DeserializeObject<MyModel>(json​) after you retrieve the response. Better yet, you can you the auto generated client to make the HTTP calls in your .NET code.

Related

Mapping Two Different Objects dynamically in C#

Object1:
{
"UserId": 123,
"Name": "testuser",
"Roles": [
{
"UserRole": "Admin"
},
{
"UserRole": "NonAdmin"
}
]
}
Object2:
{
"Id": 123,
"EmpName": "testuser",
"UserRoles": [
{
"EmpRole": "Admin"
},
{
"EmpRole": "NonAdmin"
}
]
}
I'm trying to map this object in C# using automapper. It is working fine but we need to map this object dynamically without using C# code, like keep this properties in Json file or database. Is there any other approach? We need to avoid code changes in C# if any new property is added or removed in any object, so we are looking to convert object1 to Object2 dynamically without code change.

Strongly Typed IDs and JSON Schema generation in C#

I like the idea of Strongly Typed IDs and I am using it for some time. I use it also in DTOs without and major problems... till now. I have a use case where I need to generate JSON Schema from some classes which uses Strongly Type IDs like following:
[StronglyTypedId(StronglyTypedIdBackingType.Long)]
public partial struct TweetId
{
}
public class Tweet
{
public TweetId Id {get; set;}
}
So, as described, TweetID is represented as long base type.
The problem arises when I want to generate JSON Schema from this type. I am currently using Newtonsoft.Json.Schema (I also tried some others) using this code:
JSchemaGenerator generator = new JSchemaGenerator();
JSchema quotesSchema = generator.Generate(typeof(Tweet));
The result I get is:
{
"definitions": {
"Tweet": {
"type": [
"object"
],
"properties": {
"Id": {
"$ref": "#/definitions/TweetId"
}
}
},
"TweetId": {},
},
"type": "object",
"$ref": "#/definitions/Tweet"
}
But what I want is:
{
"definitions": {
"Tweet": {
"type": [
"object"
],
"properties": {
"Id": {
"type": "integer"
}
}
}
},
"type": "object",
"$ref": "#/definitions/Tweet"
}
Do you have any idea how to achive this? Newtonsoft.Json.Schema is not mendatory.

Why does Swagger CodeGen 3.0.x generates classes with AllOf[Classname]

I'm using swagger codegen 3.0.21 for generating a C# api client.
The generators creates for all referenced classes additional classes in /Model beginning with AllOf[Classname].
Why does Swagger CodeGen generate these classes? What is their porpuse? They also have multiple errors with my sepcification.
Relevant changed part of the generated json:
"components": {
"schemas": {
"MyClass": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"propertyTwo": {
"type": "integer",
"format": "int64"
},
"propertyThree": {
"allOf": [
{
"$ref": "#/components/schemas/MySecondClass"
}
],
"nullable": true
},
"propertyFour": {
"allOf": [
{
"$ref": "#/components/schemas/MyThirdClass"
}
],
"nullable": true
},
"propertyFive": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MyFourthClass"
},
"nullable": true
},
"propertySix": {
"type": "boolean"
}
},
"additionalProperties": false
},
}
}
The constructor for MyClass is generated as following:
public MyClass(long? id = default(long?), long? propertyTwo = default(long?), propertyThree = default(), propertyFour = default(), List<MyThirdClass> propertyFive = default(List<MyFourthClass>), bool? propertySix = default(bool?))
As you can see the datatypes for propertyThree and propertyFour are just empty spaces.
We ran into the same issue. For generating a csharp client/models we actually use https://github.com/RicoSuter/NSwag/wiki/NSwagStudio which also provide you a lot of options and does generate the models properly
However for a client we needed a java generator as well and nswagstudio only supports csharp and typescript. I tried the suggestion of #NickSim that worked as a charm.

How can I deserialize the json response of azure devOps?

I am reffering my question to the Microsoft doc. I requested the azure devOps api to retrieve all repos hosted in a particular organization and project. The response is a json looking like following:
{
"count": 3,
"value": [
{
"id": "5febef5a-833d-4e14-b9c0-14cb638f91e6",
"name": "AnotherRepository",
"url": "https://dev.azure.com/fabrikam/_apis/git/repositories/5febef5a-833d-4e14-b9c0-14cb638f91e6",
"project": {
"id": "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c",
"name": "Fabrikam-Fiber-Git",
"url": "https://dev.azure.com/fabrikam/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c",
"state": "wellFormed"
},
"remoteUrl": "https://dev.azure.com/fabrikam/Fabrikam-Fiber-Git/_git/AnotherRepository"
},
{
"id": "278d5cd2-584d-4b63-824a-2ba458937249",
"name": "Fabrikam-Fiber-Git",
"url": "https://dev.azure.com/fabrikam/_apis/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249",
"project": {
"id": "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c",
"name": "Fabrikam-Fiber-Git",
"url": "https://dev.azure.com/fabrikam/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c",
"state": "wellFormed"
},
"defaultBranch": "refs/heads/master",
"remoteUrl": "https://dev.azure.com/fabrikam/_git/Fabrikam-Fiber-Git"
},
{
"id": "66efb083-777a-4cac-a350-a24b046be6be",
"name": "TestGit",
"url": "https://dev.azure.com/fabrikam/_apis/git/repositories/66efb083-777a-4cac-a350-a24b046be6be",
"project": {
"id": "281f9a5b-af0d-49b4-a1df-fe6f5e5f84d0",
"name": "TestGit",
"url": "https://dev.azure.com/fabrikam/_apis/projects/281f9a5b-af0d-49b4-a1df-fe6f5e5f84d0",
"state": "wellFormed"
},
"defaultBranch": "refs/heads/master",
"remoteUrl": "https://dev.azure.com/fabrikam/_git/TestGit"
}
]
}
The Microsoft Doc says that the api returns type GitRepository[] so I want to deserialize the json into that type but how can I do that??
Because of the count and value property I built a HelperClass like following:
public class Rootobject
{
public GitRepository[] value { get; set; }
public int count { get; set; }
}
But after the deserialization and cast into that object all the props of GitRepository are null.
Can someone help me why all the properties are null??
EDIT: This is the deserialization
static async Task Main(string[] args)
{
string accessToken = "personal_access_token";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", string.Empty, accessToken))));
var response = await httpClient.GetStringAsync("https://dev.azure.com/fabrikam/_apis/git/repositories?api-version=5.1");
var responseObject = JsonSerializer.Deserialize<Rootobject>(response);
Console.WriteLine();
}
How are you doing your deserialization? Where have you defined the GitRepository class? Have you tried deserializing into string to check if any members have changed? The documentation is from 2016, and might have changed since.
You could instead use the nuget packages provided by Microsoft to access these APIs: https://learn.microsoft.com/en-us/azure/devops/integrate/concepts/dotnet-client-libraries?view=azure-devops
I think the NuGet package you need is Microsoft.TeamFoundationServer.Client
The problem is that System.Text.Json.JsonSerializer is by default case-sensitive. GitRepository property names are PascalCase while your provided json example contains CamelCase names. So JsonSerializer can't deserialize those properties correctly.
You can override the default settings by providing JsonSerializerOptions:
var responseObject = JsonSerializer.Deserialize<Rootobject>(response, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
Also I noticed that project property is still not being deserialized. I guess it's because GitRepository has a property called ProjectReference (instead of Project) and has a DataMember attribute.
It looks like System.Text.Json doesn't respect the DataMember attribute. So I suggest you use Newtonsoft.Json library. I tested it and it works fine:
var responseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Rootobject>(response);

How can I map REST entities with my own models

I have been given a REST service which provides some strange names, see json fomart below.
I have created some classes to map them to JSON using the following line:
var data = JsonConvert.DeserializeObject<SSTR)(jsond).inhoud_b.ToArray();
I have created classes such as:
Class inhoud_b {...}
Class bidt{...}
etc.
Json:
{
"nmbr": 0,
"tp": 1,
"sort": {
"sorted": false,
"unsorted": true
},
"inhoud_b":[
{
"bidt": {
"id": "144a207b-dd48-4ebe-87cb-153e3c6179c4",
"knldge": null,
"lTT": null,
"lD": {
"id": "52",
"text": "EM"
}
}
},
{
"bidt": {
"id": "155B307b-dd48-4ebe-87cb-125487856579",
"knldge": null,
"lTT": null,
"lDg": {
"id": "523",
"text": "AM"
}
}
}
],
"first": true,
"totalElements": 2
}
My question is, how can I map these entities with my own more meaningful models and use my models in my own code rather than those entities which don't make any sense to other developers?
Thank you.
You can use the JsonPropertyAttribute to annotate your model properties with their corresponding property name in the JSON - https://www.newtonsoft.com/json/help/html/JsonPropertyName.htm

Categories