so I am trying to convert a JSON string to a list of objects that I made myself but for some reasons it keeps throwing me errors and after googling it I couldn't find my error.
Here is what throws the error. (I already tried using a list instead of an array and it still made an exception).
items[] items = JsonSerializer.Deserialize<items[]>(h.Content.ReadAsStringAsync().Result);
This is the exception I'm getting:
"The JSON value could not be converted to Scraper.items[]. Path: $ | LineNumber: 0 | BytePositionInLine: 1."
Here is what my object item looks like looks like :
public Int64 id;
public string title;
public double price;
public string currency;
public string brand_title;
public string size_title;
public user user;
public bool is_for_swap;
public string url;
public bool promoted;
public photo photo;
public int favorit_count;
public bool is_favorite;
public string badge;
public string[] conversion;
public int view_count;
(I know I am not doing propreties or any constructor. I deleted them all while trying to solve my issue. (Other objects are also there but I wont show them since I don't think they are the thing making my exceptions and I don't want this post to be unreadable))
My JSON : https://pastebin.com/AZE1AwhL
Thanks for reading this and getting some help would make me progress a lot on my project.
The JSON you have linked is not an array. It's an object, with a property items which is an array. So JsonSerializer.Deserialize<items[]> won't work. You need to deserialize to a class with an items property.
Something like this:
public class Wrapper
{
[JsonProperty("items")]
public Item[] Items { get; set; }
}
// ...
var options = new JsonSerializerOptions { IncludeFields = true };
var wrapper = JsonSerializer.Deserialize<Wrapper>(
h.Content.ReadAsStringAsync().Result,
options);
wrapper.Items // This is your array
Side note: C# naming conventions dictate you should use PascalCasing for class names. So items should be called Items or more apropriately Item since it's not a list type.
Related
I am trying to serialize a class with a generic property using the MessagePack-CSharp package. Here's a minimum reproducible example of what I'm trying to do:
using MessagePack;
[MessagePackObject(keyAsPropertyName: true)]
public class Data<T>
{
T data { get; set; }
public Data(T data)
{
this.data = data;
}
}
Data<int> testData = new(1);
byte[] bytes = MessagePackSerializer.Serialize(testData);
Console.WriteLine(MessagePackSerializer.ConvertToJson(bytes));
That program, as written, will throw an exception about not being able to find a matched constructor. If I add a parameterless constructor with an empty body, it no longer throws -- but will return {} as the converted JSON, when I really want { "data": 1 }. Is it possible to accomplish this?
I was being really stupid, I need to specify public T data { get; set; }. Alternatively the MessagePack-CSharp README has information about how to tell the serializer to target private fields.
I have a very simple object like:
public class ChargeTemplate
{
public string ChargeTemplateType;
public string TemplateCode;
public string ChargeDescription;
public string Active;
public Calculation ChargeTemplateCalculation;
public TApplication ChargeTemplateApplication;
public Taxation ChargeTemplateTaxation;
}
I'm filling out some of the fields and then passing it to this method:
public void FillChargeTemplateFields(object items)
{
foreach (var prop in items.GetType().GetFields())
{
...
}
}
Inside I'm grabbing the name and the value.
When I get down to Calculation, I want to know that it's a new class with fields so that I can throw it back up into the method to get it's field names and values. But I can't seem to figure out how to determine that it's a class as well. How do I do this?
Looking for namespace name in FieldType allowed me to determine it was one of my classes, at which point I just passed back the value.
I'm experimenting with the MVC4 WebApi for building rest/json services.
In my controller I have the method:
public HttpResponseMessage Post(dynamic message)
This contains a single object which always has two fields, type and action.
Action is either Create or Cancel.
I wrote three classes, Message, CreateMessage and CancelMessage, Message is the base class the other two inherit.
After reading the blurb on dynamic I thought I'd be able to do this:
public void ProcessMessage(dynamic message)
{
switch ((string)message.action)
{
case "CREATE":
ProcessCreateMessage(message);
break;
case "CANCEL":
ProcessCancelMessage(message);
break;
}
}
private void ProcessCancelMessage(CancelMessage message)
{
//Cancell
}
private void ProcessCreateMessage(CreateMessage message)
{
//Create
}
But I just get either a message about there not being an overload (implicit cast) or "Cannot convert type 'Newtonsoft.Json.Linq.JObject' to 'CancelMessage'"
The classes
public class Message
{
public string type { get; set; }
public string action { get; set; }
}
public class CancelMessage : Message
{
public string ref { get; set; }
public string message { get; set; }
}
The Json:
{
"type" : "type",
"action" : "cancel",
"ref" : "RefNo",
"message" : "a message"
}
What am I not getting here?
You can deserialize JSON to c# object like
var cancelMessage = new JavaScriptSerializer().Deserialize<CancelMessage>(message);
I think that you can't cast string(JSON) to object by default.
Please go through Arcrain's answer.
Deserializing JSON to .NET object using Newtonsoft (or LINQ to JSON maybe?)
I think in your case It will help you from the same url link.
You can use the C# dynamic type to make things easier. This technique also makes re-factoring simpler as it does not rely on magic-strings.
Json
The json string below is a simple response from an http api call and it defines two properties: Id and Name.
{"Id": 1, "Name": "biofractal"}
C#
Use JsonConvert.DeserializeObject<dynamic>() to deserialize this string into a dynamic type then simply access its properties in the usual way.
var results = JsonConvert.DeserializeObject<dynamic>(json);
var id = results.Id;
var name= results.Name;
Note: The NuGet link for the NewtonSoft assembly is http://nuget.org/packages/newtonsoft.json
Hope it will resolve your problem.
Here's another solution, using information posted by Janty and Babinicz
Using the ApiController in MVC 4 as I am, if you state dynamic as your single incoming parameter.
(I'm following Microsoft's beginner's guides to Web Api in MVC4)
When you try to cast dynamic to something, it's supposed to magically work, but I was getting an error.
Tried writing a custom cast operator, but you can't do that to or from dynamic
But it appears that dynamic is a lot like object in that it knows what it's underlying type is, and that type is Newtonsoft's JObject
And that casting to and from dynamic just does normal casting, compiled at runtime instead of design time.
So by adding implicit cast operators to the model classes:
public class Message
{
public string type { get; set; }
public string action { get; set; }
}
public class CancelMessage : Message
{
public string ref { get; set; }
public string message { get; set; }
public static implicit operator CancelMessage(JObject message)
{
var output = JsonConvert.DeserializeObject<CancelMessage>(message.ToString());
return output;
}
}
public void ProcessMessage(dynamic message)
{
switch ((string)message.action)
{
case "CANCEL":
ProcessCancelMessage(message);
break;
}
}
private void ProcessCancelMessage(CancelMessage message)
{
//Cancel
}
That just works.
Of course, it's also arguable that if I just pass this dynamic thing around, my code will just work as long as the field names in the json match what's expected.
I'm pretty sure an enum isn't what I want. What I want is a list of named items
CustomerLookup = "005",
CustomerUpdate = "1010"
The "005" and "1010" aren't my values, they are the values I need to send to a 3rd party that I have no control over. There are close to 500 of them. I just want my code to look nice.
Instead of
SendRequest("005");
I'd rather see
SendRequest(RequestType.CustomerLookup);
Anyone have any self-documenting ideas without getting all crazy in the code?
Anything wrong with:
public static class RequestType
{
public static readonly string CustomerLookup = "005";
// etc
}
or
public static class RequestType
{
public const string CustomerLookup = "005";
// etc
}
? Or if you want more type safety:
public sealed class RequestType
{
public static readonly RequestType CustomerLookup = new RequestType("005");
// etc
public string Code { get; private set; }
private RequestType(string code)
{
this.Code = code;
}
}
That will basically give you a fixed set of values (the constructor is private, so outside code can't create different instances) and you can use the Code property to get at the related string value.
How about using some kind of associative array?
The way you are already doing it seems right to me.
You are clearly defining the requesttype values in your code without ambiguity and when you come to use them you have intellisense on your side.
I think the real issue is how to get the 500 values into your code without any tyypos!
I have a lot of constant string values in my application which I want to have as strongly typed objects in C# for code reuse and readability. I would like to be able to reference the string value like so:
Category.MyCategory //returns a string value ie “My Category”
Category.MyCategory.Type.Private //returns a string value ie “private”
Category.MyCategory.Type.Shared //returns a string value ie “shared”
I have started by implementing the following classes each containing a list of public string valued fields with a public property which exposes the child.
Category, MyCategory, Type
However I already know this is not the way to go so could do with a bit of advice on this one.
An example of this is where I am using the Syndication classes to add a category to an atom feed. I am creating the items in this feed dynamically so need to use the notation as shown.
item.Categories.Add( new SyndicationCategory
{
Scheme = Category.PersonType,
Label="My Category",
Name=Category.MyCategory.Type.Private
});
Keep your string constants close to where you need them, IMO having a class that just declares constants is an OO antipattern
Why not simply implement them as classes with overridden ToString implementations?
public class MyCategory
{
private readonly MyType type;
public MyCategory()
{
this.type = new MyType();
}
public MyType Type
{
get { return this.type; }
}
// etc.
public override string ToString()
{
return "My Category";
}
}
public class MyType
{
public override string ToString()
{
return "My Type";
}
// more properties here...
}
However, for general purposes, consider whether the strings in themselves don't represent concepts that are better modeled as full-blown objects.
I completely agree with Rob. If you still want to have a "bag of strings", you could try using nested classes, something like below. I don't really like it, but it works.
public class Category
{
public class MyCategory
{
public const string Name = "My Category";
public class Type
{
public const string Private = "private";
public const string Shared = "shared";
}
}
}