Deserializing of Google's Translate API result in C# - c#

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.)

Related

Convert json to C# classes with generic property

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:

Convert a POCO to json using only certain fields

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; }

Deserializing an unnamed array

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.

ServiceStack Json deserializing incorrectely

I've got a RequestDto, let's say Class A Dto, it contains a self defined type property:
// C# code
public Class MyObject
{
public string A { get; set; }
public string B { get; set; }
}
public Class ADto
{
public List<MyObject> MO { get; set;}
}
When I am trying to send the Dto using Json, the Json object looks like this:
{"MO":[{"A":"String","B":"a"},{"A":"String","B":"b"}]}
but the object I am receiving will be null.
However if I change the Json string into:
{MO:[{A:"String",B:"a"},{A:"String",B:"b"}]}
I lose the quotation marks on the objects' names and it works.
The correct format of Json should include those quotation marks right?
Why is this happening?
ServiceStack does serializes and deserializes valid JSON which requires every property name to be quoted however you're saying that the text below works:
{MO:[{A:"String",B:"a"},{A:"String",B:"b"}]}
However this isn't valid JSON, it instead looks like ServiceStack's JSV Format
You haven't mentioned where you're sending the JSV Format or have provided the Raw HTTP Request (for us to work it out), but I'm assuming if you're using Postman (mentioned in your comments) than you're trying to send JSON in the ?QueryString which isn't allowed.
But ServiceStack does support sending complex object graphs on the QueryString using JSV.
Since you're sending a complex type you'd either POST the request as either JSON or www-form-urlencoded Form Data or if you want to pass it in the QueryString you need to convert it to JSV.
In future please include the Raw HTTP Request as this question lacks any context on where you're changing the JSON string, how you're trying to use it or what's actually being sent, where you're sending it to, etc - making it impossible to guess what the issue is.
Change your class to
public Class MyObject
{
public string Mobile { get; set; }
public string Name { get; set; }
}
public Class ADto
{
public List<MyObject> MO { get; set;}
}
Then your json should be
{MO:[{Mobile:"0556604",Name:"Peter"},{Mobile:"4565466",Name:"John"}]}

How to ignore data in JSON.NET that changes between returns

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);

Categories

Resources