I have the following json structure from an api return:
{
"firstName": "test first",
"lastName": "test last",
"moduleReports": [
{
"completion": "Nothing shared",
"thoughts": "example",
"componentTitle": "CareerCorner"
},
{
"thoughts": "example",
"componentTitle": "CareerLIbrary"
},
{
"completionDate": "0001-01-01T00:00:00",
"componentTitle": "Discoverer"
},
{
"completionDate": "0001-01-01T00:00:00",
"componentTitle": "Explorer"
},
{
"workValues": [
"independence",
"relationships"
],
"componentTitle": "Navigator"
},
{
"personalityTypes": [
"Creator",
"Doer"
],
"componentTitle": "Pathfinder"
},
{
"reflection": "example",
"completionDate": "0001-01-01T00:00:00",
"componentTitle": "QuickPic"
},
{
"careerGroup": "Ideas",
"componentTitle": "Scout"
},
{
"improveAtSkills": [
"listen",
"speak"
],
"goodAtSkills": [
"decision",
"solve"
],
"componentTitle": "Trekker"
}
]
}
I tried to create the classes myself and came up with
public class ModuleReport
{
public string completion { get; set; }
public string thoughts { get; set; }
public string componentTitle { get; set; }
public DateTime? completionDate { get; set; }
public List<string> workValues { get; set; }
public List<string> personalityTypes { get; set; }
public string reflection { get; set; }
public string careerGroup { get; set; }
public List<string> improveAtSkills { get; set; }
public List<string> goodAtSkills { get; set; }
}
public class ModuleResult
{
public string firstName { get; set; }
public string lastName { get; set; }
public List<ModuleReport> moduleReports { get; set; }
}
but when I call
var mResults = JsonConvert.DeserializeObject<List<ModuleResult>>( jsonString );
in the controller I get the following error
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[...Reports.User.ModuleResults]' 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<T>) 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.
I have tried following the advice found in the answers here: How to deserialize JSON with dynamic and static key names in C# and hereSerialize/Deserialize dynamic property name using JSON.NET but I keep getting the same error.
I started to build the following
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
{
var responseObject = JObject.Load( reader );
ModuleResult response = new ModuleResult
{
firstName = (string)responseObject[ "firstName" ],
lastName = (string)responseObject[ "lastName" ],
};
var varData = new Dictionary<string, object>();
foreach ( var property in responseObject.Properties() )
{
if ( property.Name == "firstName" || property.Name == "lastName" )
{
continue;
}
varData.Add( property.Name, property.Value );
}
response.VarData = varData;
return response;
}
but when I put it into place I realized that it would just add the entire "moduleResults" node as key and all it's contents as the value. So back to square one.
I know the issue is accessing the "moduleReports" json array and properly deserializing those key/value pairs, but I'm having a hell of a time figuring out how to dig in to that nested array and then how to deal with the changing key/value pairs.
CodePudding user response:
Why do you want to deserialize it as List<ModuleResult>
, when the JSON structure you've provided indicates that it is a single ModuleResult
object?
Just change
var mResults = JsonConvert.DeserializeObject<List<ModuleResult>>( jsonString );
To
var mResults = JsonConvert.DeserializeObject<ModuleResult>( jsonString );
and it will be deserialized correctly.
CodePudding user response:
try this
var jD = JsonConvert.DeserializeObject<Root>(json);
output=JsonConvert.SerializeObject(jD);
output
{"firstName":"test first","lastName":"test last","moduleReports":[{"completion":"Nothing shared","thoughts":"example","componentTitle":"CareerCorner"},{"thoughts":"example","componentTitle":"CareerLIbrary"},{"componentTitle":"Discoverer","completionDate":"0001-01-01T00:00:00-03:30"},{"componentTitle":"Explorer","completionDate":"0001-01-01T00:00:00-03:30"},{"componentTitle":"Navigator","workValues":["independence","relationships"]},{"componentTitle":"Pathfinder","personalityTypes":["Creator","Doer"]},{"componentTitle":"QuickPic","completionDate":"0001-01-01T00:00:00-03:30","reflection":"example"},{"componentTitle":"Scout","careerGroup":"Ideas"},{"componentTitle":"Trekker","improveAtSkills":["listen","speak"],"goodAtSkills":["decision","solve"]}]}
classes
public partial class Root
{
[JsonProperty("firstName")]
public string FirstName { get; set; }
[JsonProperty("lastName")]
public string LastName { get; set; }
[JsonProperty("moduleReports")]
public ModuleReport[] ModuleReports { get; set; }
}
public partial class ModuleReport
{
[JsonProperty("completion", NullValueHandling = NullValueHandling.Ignore)]
public string Completion { get; set; }
[JsonProperty("thoughts", NullValueHandling = NullValueHandling.Ignore)]
public string Thoughts { get; set; }
[JsonProperty("componentTitle")]
public string ComponentTitle { get; set; }
[JsonProperty("completionDate", NullValueHandling = NullValueHandling.Ignore)]
public DateTimeOffset? CompletionDate { get; set; }
[JsonProperty("workValues", NullValueHandling = NullValueHandling.Ignore)]
public string[] WorkValues { get; set; }
[JsonProperty("personalityTypes", NullValueHandling = NullValueHandling.Ignore)]
public string[] PersonalityTypes { get; set; }
[JsonProperty("reflection", NullValueHandling = NullValueHandling.Ignore)]
public string Reflection { get; set; }
[JsonProperty("careerGroup", NullValueHandling = NullValueHandling.Ignore)]
public string CareerGroup { get; set; }
[JsonProperty("improveAtSkills", NullValueHandling = NullValueHandling.Ignore)]
public string[] ImproveAtSkills { get; set; }
[JsonProperty("goodAtSkills", NullValueHandling = NullValueHandling.Ignore)]
public string[] GoodAtSkills { get; set; }
}