I am trying to get release progressions for a certain project using the Octopus Client (github source) calling the /api/progression/<project-id> endpoint like this:
// _repository is of type IOctopusRepository
_repository.Client.Get<ProgressionResource>($"/api/progression/{projectId}");
Which is immediately throwing an OctopusDeserializationException saying:
Unable to process response from server: Cannot deserialize the current
JSON object (e.g. {"name":"value"}) into type
'System.Linq.IOrderedEnumerable`1[Octopus.Client.Model.DashboardItemResource]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET
type (e.g. not a primitive type like integer, not a collection type
like an array or List) that can be deserialized from a JSON object.
JsonObjectAttribute can also be added to the type to force it to
deserialize from a JSON object.
Path 'Releases[0].Deployments.Environments-1.Id', line 55, position 15.. Response content: {
"Environments": [
{
"Id": "Environments-1",
"Name": "test-environment"
},
In each Release (of type ReleaseProgressionResource) from the Releasesthere is a Deployments prop which is of type Dictionary<string,IOrderedEnumerable<DashboardItemResource>>. However, it seems like the client (that has been made to consume this API) cannot serialize that. From the exception message, it seems like the client is trying to parse that as a JSON array.
Here's a sample Deployments part of the endpoint response in raw JSON (with some dummy data):
"Deployments": {
"Environments-1": {
"Id": "Deployments-12345",
"ProjectId": "Projects-123",
"EnvironmentId": "Environments-1",
"ReleaseId": "Releases-12345",
"DeploymentId": "Deployments-12345",
"TaskId": "ServerTasks-12345",
"ReleaseVersion": "5.4.3",
"Created": "2016-09-22T21:26:38.886+00:00",
"QueueTime": "2016-09-22T21:26:38.855+00:00",
"CompletedTime": "2016-09-22T21:29:48.355+00:00",
"State": "Success",
"HasPendingInterruptions": false,
"HasWarningsOrErrors": false,
"ErrorMessage": "",
"Duration": "3 minutes",
"IsCurrent": true,
"IsPrevious": false,
"IsCompleted": true,
"Links": {
"Self": "/api/deployments/Deployments-12345",
"Release": "/api/releases/Releases-12345",
"Task": "/api/tasks/ServerTasks-12345"
}
}
}
Does anyone have any ideas what might be happening/what I might be doing wrong?
Thanks in advance.
Is that the whole Deployment object? JSON objects need to be enclosed in brackets.
{
"Deployments": {
"Environments-1": {
"Id": "Deployments-12345",
"ProjectId": "Projects-123",
"EnvironmentId": "Environments-1",
"ReleaseId": "Releases-12345",
"DeploymentId": "Deployments-12345",
"TaskId": "ServerTasks-12345",
"ReleaseVersion": "5.4.3",
"Created": "2016-09-22T21:26:38.886+00:00",
"QueueTime": "2016-09-22T21:26:38.855+00:00",
"CompletedTime": "2016-09-22T21:29:48.355+00:00",
"State": "Success",
"HasPendingInterruptions": false,
"HasWarningsOrErrors": false,
"ErrorMessage": "",
"Duration": "3 minutes",
"IsCurrent": true,
"IsPrevious": false,
"IsCompleted": true,
"Links": {
"Self": "/api/deployments/Deployments-12345",
"Release": "/api/releases/Releases-12345",
"Task": "/api/tasks/ServerTasks-12345"
}
}
}
}
Related
I'm working on a project that involves automating API calls using a Swagger Definition. I download the swagger.json file. The structure of the JSON Object I need to parse is not consistent. When parsing paths, there are a list of objects, then within that they have the methods that can be used for that specific path. I can retrieve just the path using various string methods but my question was, is there a good way to parse json if the JSON is structured in such a way that it does not have a firm key? Here is an example of what I mean:
{"/user": {
"post": {
"tags": [
"user"
],
"summary": "Create user",
"description": "This can only be done by the logged in user.",
"operationId": "createUser",
"consumes": [
"application/json"
],
"produces": [
"application/json",
"application/xml"
],
"parameters": [
{
"in": "body",
"name": "body",
"description": "Created user object",
"required": true,
"schema": {
"$ref": "#/definitions/User"
}
}
],
"responses": {
"default": {
"description": "successful operation"
}
}
}
}
If I wanted to just parse that path and retrieve the method object how could I go about that considering sometimes the object will be "post" or sometimes it will be "get", "put", etc depending on what is allowable for the path.
JObject jsonResp = swaggerDownload();
JObject paths = (JObject)jsonResp["paths"];
foreach (var i in paths)
{
string pathToString = i.ToString();
var shaveSomethings = pathToString.Substring(1, something.Length - 2);
var pathAndJson = shaveSomethings.Split(new[] { ',' }, 2);
string correctJsonStructure = "{\"" + pathAndJson[0] + "\":" + pathAndJson[1] + "}";
JObject bd = JObject.Parse(correctJsonStructure);
//dynamic pathsTest = JsonConvert.DeserializeObject<dynamic>(correctJsonStructure);
//JObject result = JsonConvert.DeserializeObject<JObject>(correctJsonStructure);
//Console.WriteLine(bd["/user"]);
}
The swagger.json file should have full definition of each entity that endpoints return. You can follow How to create Rest API client to get a working client.
I've dealt with an API where responses didn't always match the definition. I saved all responses to a store/log first and then would try to de-serialize JSON. In case of an exception I would go back to store/log and see what was different and update my code to accommodate for the change. After few iterations there were no new changes and the ordeal was over.
Hope that helps.
According to the SendGrid docs, it seems like I can send a template to a list by inputting the template ID and list ID into the singlesend call. However when I call this method with those JSON fields, I get an error.
JSON:
{"sender_id":779461,"filter":{"list_ids":["572d0ae8-c665-4265-8e90-28fda56d9409"],"send_to_all":"false"},"template_id":"d-2b8c55e6e0a6463ab096d2e146d77c2c"}
Error: {
"errors": [
{
"field": "",
"message": "json could not be unmarshalled"
}
]
}
I've been trying to get the correct JSON format for a while now, with no luck due to this non-descriptive error. I am also using the C# library for .NET and I cannot find any methods to set a list id to the message. The SendGrid support portal is broken so I cannot reach out to them.
try your json like this send_to_all is not of type string but boolean:
{
"sender_id": 779461,
"filter": {
"list_ids": [
"572d0ae8-c665-4265-8e90-28fda56d9409"
],
"send_to_all": false
},
"template_id": "REAL UUID"
}
As part of contract tests I have to validate json response I got from rest-endpoint against json-schema present in a file. I'm using NJsonSchema and was not able to perform this.
Json-schema in file is as something below
{
'type': 'object',
'properties': {
'remaining': {
'type': 'integer',
'required': true
},
'shuffled': {
'type': 'boolean',
'required': true
}
'success': {
'type': 'boolean',
'required': true
},
'deck_id': {
'type': 'string',
'required': true
}
}
}
Json I have to validate is something like below
{ 'remaining': 52, 'shuffled': true, 'success': true, 'deck_id': 'b5wr0nr5rvk4'}
Can anyone please throw some light (with examples) on how to validate json with jsonschema using NJsonSchema or Manatee.Json.
Disclaimer: I'm the author of Manatee.Json.
That looks like a draft-03 schema (the required keyword was moved out of the property declaration in draft-04). I'm not sure if NJsonSchema supports schemas that old; Manatee.Json doesn't.
JSON Schema is currently at draft-07, and draft-08 is due out soon.
My suggestion is to rewrite the schema as a later draft by moving the required keyword into the root as a sibling of properties. The value of required becomes an array of strings containing the list of properties that are required.
{
"type": "object",
"properties": {
"remaining": { "type": "integer" },
"shuffled": { "type": "boolean" },
"success": { "type": "boolean" },
"deck_id": { "type": "string" }
},
"required": [ "remaining", "shuffled", "success", "deck_id" ]
}
By doing this, it'll definitely work with Manatee.Json, and I expect it'll work with NJsonSchema as well.
If you have specific questions about using Manatee.Json, hit me up on my Slack workspace. There's a link on the GH readme.
I have a problem;
I would to know if there is a method to parse json file without having a unique format. So it may have different attributes but all of them contain the attribute Status but it can be in double.
{
"requestid": "1111",
"message": "db",
"status": "OK",
"data": [
{
"Status": "OK", // this one I would to test first to read the other attributes
"fand": "",
"nalDate": "",
"price": 1230000,
"status": 2
}
]
}
With https://www.newtonsoft.com/json
Data data = JsonConvert.DeserializeObject<Data>(json);
And create the class Data with the interesting data inside the json
The defacto standard Json serializer for .NET is Newtonsoft.Json (How to install). You can parse the Json into an object graph and work on that in any order you like:
namespace ConsoleApp3
{
using System;
using Newtonsoft.Json.Linq;
class Program
{
static void Main()
{
var text = #"{
'requestid': '1111',
'message': 'db',
'status': 'OK',
'data': [
{
'Status': 'OK', // this one I would to test first to read the other attributes
'fand': '',
'nalDate': '',
'price': 1230000,
'status': 2
}
]
}";
var json = JObject.Parse(text);
Console.WriteLine(json.SelectToken("data[0].Status").Value<string>());
Console.ReadLine();
}
}
}
I am doing some work with C#, AJAX and JSON and am getting a Self referencing loop error. I am managing to get around this using the JsonIgnore attribute, but I was wondering if someone can give me a proper explanation as to what is actually happening here.
Many thanks.
Dave
We don't get much detail on your problem, but it's probably exactly what you're describing: a loop of self-reference, or a circular chain of references.
Say you've got a variable of the type User that has a property public UserImage Image. Now, say the type UserImage has a property User that references back to the user.
In your .NET code, it's just that. myImage.User gives yo uthe user, myUser.Image gives you the image. But imagine you want to serialize myUser (into JSON, say). Then you have to cycle every property of User and serialize that, recursively. The serializer would start off like this
{ "ID": 1, "Image": { ...
now it has to serialize the user image. And remember UserImage has the variable "User".
{ "ID": 1, "Image": { "Path": "image.src", "User": {
but the user is the very same user that we're trying to reference
{ "ID": 1, "Image": { "Path": "image.src", "User": { "ID": 1, "Image":
now we have to serialize the image for that user, but that, again, is the same image as before:
{
"ID": 1,
"Image": {
"Path": "image.src",
"User": {
"ID": 1,
"Image": {
"Path": "image.src",
"User": {
"ID": 1,
"Image": {
"Path": "image.src",
"User": {
"ID": 1,
"Image": {
"Path": "image.src",
"User":
so we never reach an end product if we're constantly serializing a circular reference.