I have json data as below:
{
status: "success",
data: {
custid1: 723,
custid2: 670,
custid3: 430
}
}
As per https://json2csharp.com/, C# classes should be like below:
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
public class Data {
public int custid1 { get; set; }
public int custid2 { get; set; }
public int custid3 { get; set; }
}
public class Root {
public string status { get; set; }
public Data data { get; set; }
}
But I dont like Data class above, it has custid1, custid2 as hard coded. I know here json data is like that so classes are generated accordingly but can we make some generic design which can parse below line?
var result = JsonConvert.DeserializeObject<Root>(json);
I feel that tools like Json2CSharp.com are only intended for scaffolding and prototyping rather than for directly-usable C# code. So go ahead and use it to quickly create initial code for your project, but you likely will need to tweak it for production use - in this case one of those tweaks you need to make is to change data: entry in the Root DTO class from having its own class Data to being a Dictionary<String,Int32> instead so that it can accommodate the dynamic nature of the data: property in production JSON data.
Side-note: You should use PascalCase for all class properties in your C# code - but you can configure your JSON serializer to automatically map the camelCase properties in the JSON.
If you're using Newtonsoft.Json then use CamelCaseNamingStrategy or set an explicit [JsonProperty( "camelCaseName" )]. You don't even have to do this manually because JSON2CSharp.com can do it automatically for you:
It's in the Options menu next to the Convert button:
Related
I am attempting to use JsonSerializer.Deserialize() from System.Text.JSON in .NET 6.
I have no control over the format of the JSON.
I have used it successfully in the past but now the data I need to consume is more complicated (but not VERY complicated). I am assuming that I am simply describing my data incorrectly.
I have tried several things.... but the description below is the only way so far that I could consume the data at all.
I think my biggest problem is that I am trying to use the wiz-bang "Paste Special -> Paste JSON as Classes" without really understanding how to form my classes for serialization/deserialization.
Here is a simple example of the JSON I am trying to consume:
[
{
"version": "1.0b",
"sub_version": "x.y.barf"
},
{
"somestring": "I am a string",
"isCool": false,
"a_cool_array": [
"bob",
"jill",
"pete"
]
}
]
If I use the whiz-bang "Paste Special" tool, I get the following generated for me.
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string version { get; set; }//<-- I need these to remain in their own object
public string sub_version { get; set; }//<-- I need these to remain in their own object
public string somestring { get; set; }
public bool isCool { get; set; }
public string[] a_cool_array { get; set; }
}
Here is the problem that I have.
The whiz-bang tool put my first object (with one version strings) and second (more complicated) object into the same object.
If I use a call like this:
var deserializedJSON = JsonSerializer.Deserialize<List<Class1>>(myJSONTextHere);
I end up with two objects in the list.
The first one has the versions filled out, the second one only has the other fields filled out.
This all makes sense to me but I don't know how to get around the problem.
I need these objects to model the JSON and I need them to save back in the same format when I re-serailize the modified classes elsewhere. This isn't my exact problem as I have simplified it for the question.
I have found one way around this problem.
It is ugly but seems to work. I hate that my code has to know about the data it is manipulating.
I used the actual JSON DOM to split the two disparate classes into individual JSON objects, then used the class de-serializer to load the individual objects into their given types.
In the following example, I am not checking anything.. I happen to know the order of the objects. I could check the raw JSON to make sure it was what I was looking for. In this case, I don't need to.
So, instead of taking the class structure as pasted by the super spiffy "Paste Classes from JSON" thingamajigger.. I split the classes myself.
Like this:
public class VersionClass
{
public string version { get; set; }
public string sub_version { get; set; }
}
public class DataClass
{
public string somestring { get; set; }
public bool isCool { get; set; }
public string[] a_cool_array { get; set; }
}
Then, I can load the JSON into the objects I need like this:
using var jsonDoc = JsonDocument.Parse(jsonText);
var versionClass = jsonDoc.RootElement[0].Deserialize<VersionClass>();
var dataClass = jsonDoc.RootElement[1].Deserialize<DataClass>();
I hope this helps someone having the same problem.
Your json needs to look like this:
{
"class1": [
//more json
],
"class2": [
//more json
]
}
Then you will have:
public class RootObject
{
// class1 and 2 in here
}
public class Class1
{
}
public class Class2
{
}
I have an object, Project, that contains many fields, some complex some not. It is an EF class, so I can't edit it to add attributes.
I just want to generate a JSON object containing 2 of the fields (one int (id) and one string (name))
I'd hate to create another ViewModel just for this...
In my viewmodel I have a List<Project>. Is there a way to use HTML helpers to get a JSON representation of only the properties I choose without using attributes?
Here is an example of the Project class:
public class Project
{
public int Id {get; set; } <-- Serialize this
public string Name { get; set; } <-- Serialize this
public Object AnotherObject [ Get; Set; } <-- Ignore this
....
}
I'd like it to become:
[{"id":"27","name":"test1"},{"id":"34","name":"test2"},{"id":"35","name":"test3"}]
The ultimate goal here to is output the json directly to the view as a var so that it can be used in building a JsGrid.
If there is a way to do it with Html helpers, that would be great.
Thanks!
Json.NET has a great built in ignore feature. If you tag the Property you want to exclude with the [JsonIgnore] attribute, the serializer will not serialize that property.
[JsonIgnore]
public bool IsValid { get; set; }
I am having difficulty writing the appropriate annotations to represent data which is returned from a JSON Get request which returns data like so:
[{"ProductCode":"0129923083091","Description":"DIESEL ","SalesLitres":6058.7347,"SalesValue":6416.2000},{"ProductCode":"0134039344902","Description":"UNLEADED ","SalesLitres":3489.8111,"SalesValue":3695.7100},
...
]
(ellipsis above just indicating that I could have variable number of these items returned)
In my model class (I am using MVVM approach for a Xamarin project but that's not over relevant here) I am using annotations to represent the model attributes
namespace App8.Models
{
public class ReportRow
{
[JsonProperty("ProductCode")]
public string ProductCode { get; set; } = string.Empty;
[JsonProperty("Description")]
public string Description { get; set; } = string.Empty;
[JsonProperty("SalesLitres")]
public double SalesLitres { get; set; } = 0.0;
[JsonProperty("SalesValue")]
public double SalesValue { get; set; } = 0.0;
}
}
I would like to annote another class which shows the container/contained relationship. However, I coming unstuck as there is no JSON attribute to provide in the annotation to represent the "root" of the returned collection.
I'd have no problem mapping the JSON to an object model for any JSON arrays which are named within the returned JSON. In that case I could create another class with a named JSON attribute which contained a C# List but I am trying to provide an appropriate model mapping for JSON which returns a list of items within an unnamed array.
Any ideas how I could approach this?
To deserialize that JSON, use:
JsonConvert.DeserializeObject<List<ReportRow>>(json)
(or any variant you wish, the key here is asking to deserialize a ICollection of ReportRow. It could be your own class implementing ICollection, or any of the builtins)
The same idea follows to JsonTextReader or whatever other means of deserializing JSON.NET offers. Just use a ICollection<YourType> as target type.
I'm parsing JSON data return by a third party.
I have my class generated with JSON2CSharp which works for the first sample we received. I tweaked it to have some JsonProperty settings so that it doesn't require certain properties that are not always present.
Now I received more samples and one of the datablobs changed format
from needing
public Translations Translations { get; set; }
to
public List<Translations> Translations { get; set; }
The blob however is information we do not need, for both performance and not having to deal with that and other pieces of information we do not need changing format, it would be ideal to just ignore it when deserializing it.
Now the real question is, should "JsonIgnore" just ignore the entire blob of data irregardless if it is in a different format then defined in the class? Or do I have to program around that?
So if I do
[JsonIgnore]
public string Translations { get; set; }
will it also ignore Translations when it gets sent a list or an object?
Can I use the same syntax with JsonIgnore as I can with JsonProperty and just say
[JsonIgnore(PropertyName = "translations")]
or does JsonIgnore just toss out anything it receives?
Additionally question:
Is it convention that when there are no translations, I get:
"translations":[]
and when there are translations I get:
"translations":{"CA":"blabla","DD":"C : blablah"}
Or is this likely a bug in the third party's website?
ADDED:
1: The Translations can switch between string, list and object between every fetch of the JSON.
2: For using DataMembers ignoring everything I don't actually need, in a class with subclasses, do I have to tell it that the subclass is [DataMember] or the subclasses properties are [DataMember]?
I would explicitly specify exactly the properties I wanted serialized/deserialized in my data class using DataContractAttribute and DataMemberAttributes for the members you actually want to deserialize.
This is opt in, so no attempt is made to shoehorn anything extra in your JSON into your data class, and anything extra in your data class doesn't show up in serialized JSON.
So assuming your class right now looks like this:
class MyData {
// Old member
// public Translations Translations { get; set; }
public List<Translation> Translations { get; set; }
public string ThisShouldBeSerialized { get; set; }
}
You can change it so things that you want serialized are explicitly marked as such, and anything not marked for serialization is ignored by default:
[DataContract]
class MyData {
// Old member
// public Translations Translations { get; set; }
public List<Translation> Translations { get; set; }
[DataMember]
public string ThisShouldBeSerialized { get; set; }
}
And then:
var myJSON = #"{
'ThisShouldBeSerialized': 'test',
'Translations': {
'Some' : 'Strange',
'Data' : 'Blob'
}
}";
var result = JsonConvert.DeserializeObject<MyData>(myJSON);
I'm trying to deserialize Google's Translate API JSON response into an C# object using JavaScriptSerializer. However, it always says Type 'TranslateAPI.Models.Translations' is not supported for deserialization of an array.. I double checked whether I have correctly created models for this object and it seems right. Here are my models:
TranslateResult
public TranslateData data { get; set; }
TranslateData
public Translations translations { get; set; }
Translations
public TranslatedText[] translatedText { get; set; } // I have also tried List<TranslatedText> which also doesn't work
TranslatedText
public string translatedText { get; set; }
The json returned from Google looks like this:
{data: {
translations: [
{translatedText: "Hello world"}
]
}
Any idea what I'm doing wrong?
Thanks
PS. It could be useful to mention, that I'm deserializing it like so: TranslateResult translateResult = js.Deserialize <TranslateResult>(json);
I suspect you don't need the Translations class at all. You've got:
An object containing a data property
The data property value is an object containing a translations property
The translations property value is an array
Each element of the array is an object with a translatedText property
So that sounds to me like your TranslateData class should be:
TranslateData
public Translation[] translations { get; set; }
Translation // Renamed from TranslatedText
public string translatedText { get; set }
(I'd also recommend that you rename the properties to follow normal C# naming conventions, and then apply attributes to help with the JSON conversion if you need to. I haven't used JavaScriptSerializer for a while, but I'm sure it's feasible. You shouldn't need to work with nasty property names in your C# code.)