I am trying to deserialize an AchievementConfigurations: list REST Response from here https://developers.google.com/games/services/publishing/api/achievementConfigurations/list.
The problem is that this line only fills out the top level object and the List remains empty. No error messages are throw which makes this difficult to track down what is going on. I used a website to generate the json structured classes and after that I removed the duplicates which where unnecessary.
The response looks like this, I have removed the achievementConfiguration resource because it is really long but it can be found here https://developers.google.com/games/services/publishing/api/achievementConfigurations#resource
{
"kind": "gamesConfiguration#achievementConfigurationListResponse",
"nextPageToken": string,
"items": [
achievementConfigurations Resource
]
}
I have a series of classes I have created mirroring the data starting with the AchievementConfigurationListResponse class
public class AchievementConfigurationListResponse
{
public string kind = "gamesConfiguration#achievementConfigurationListResponse";
public string nextPageToken = "";
List<AchievementConfigurationResource> items = new List<AchievementConfigurationResource>();
}
Next up is the AchievementConfigurationResource which is an item in the list, it has several nested objects
public class AchievementConfigurationResource
{
public static string[] types = new string[] { "STANDARD", "INCREMENTAL" };
public static string[] states = new string[] { "REVEALED", "HIDDEN", "UNLOCKED" };
public string kind = "gamesConfiguration#achievementConfiguration";
public string token = "";
public string id = "";
public string achievementType = types[0];
public string initialState = states[0];
public int? stepsToUnlock;
public AchievementConfigurationDetail draft = new AchievementDataResource();
public AchievementConfigurationDetail published = new AchievementDataResource();
}
Those nested object are of this type of AchievementConfigurationDetail
public class AchievementConfigurationDetail
{
public string kind = "gamesConfiguration#achievementConfigurationDetail";
public LocalizedStringBundle name = new LocalizedStringBundle();
public LocalizedStringBundle description = new LocalizedStringBundle();
public int pointValue = 5;
public string iconUrl = "";
public int sortRank = 1;
}
Which contains several LocalizedStringBundles
public class LocalizedStringBundle
{
public string kind = "gamesConfiguration#localizedStringBundle";
public List<Translation> translations = new List<Translation>();
public class Translation
{
public string kind = "gamesConfiguration#localizedString";
public string locale = "en-US";
public string value = "";
}
}
I call this on the json with the following line:
AchievementConfigurationListResponse res = JsonConvert.DeserializeObject<AchievementConfigurationListResponse>(content);
Here is a copy of the response, sensitive data removed but the keys and structure are all intact. This one only contains a single record because the full file is something like 5000 lines long.
{
"kind": "gamesConfiguration#achievementConfigurationListResponse",
"items": [
{
"kind": "gamesConfiguration#achievementConfiguration",
"token": "Unique Token",
"id": "Unique ID",
"achievementType": "STANDARD",
"initialState": "REVEALED",
"draft": {
"kind": "gamesConfiguration#achievementConfigurationDetail",
"name": {
"kind": "gamesConfiguration#localizedStringBundle",
"translations": [
{
"kind": "gamesConfiguration#localizedString",
"locale": "en-US",
"value": "Name"
}
]
},
"description": {
"kind": "gamesConfiguration#localizedStringBundle",
"translations": [
{
"kind": "gamesConfiguration#localizedString",
"locale": "en-US",
"value": "Description"
}
]
},
"pointValue": 5,
"iconUrl": "Icon url",
"sortRank": 1
},
"published": {
"kind": "gamesConfiguration#achievementConfigurationDetail",
"name": {
"kind": "gamesConfiguration#localizedStringBundle",
"translations": [
{
"kind": "gamesConfiguration#localizedString",
"locale": "en-US",
"value": "Name"
}
]
},
"description": {
"kind": "gamesConfiguration#localizedStringBundle",
"translations": [
{
"kind": "gamesConfiguration#localizedString",
"locale": "en-US",
"value": "Description"
}
]
},
"pointValue": 5,
"iconUrl": "Icon url",
"sortRank": 1
}
}
]
}
Json.NET does not serialize private members by default. Thus you need to make AchievementConfigurationListResponse.items be public:
public List<AchievementConfigurationResource> items = new List<AchievementConfigurationResource>();
Alternatively, mark it with [JsonProperty] which enables serialization of private members:
[JsonProperty]
List<AchievementConfigurationResource> items = new List<AchievementConfigurationResource>();
Related
I have this JSON:
[
{
"Attributes": [
{
"Key": "Name",
"Value": {
"Value": "Acc 1",
"Values": [
"Acc 1"
]
}
},
{
"Key": "Id",
"Value": {
"Value": "1",
"Values": [
"1"
]
}
}
],
"Name": "account",
"Id": "1"
},
{
"Attributes": [
{
"Key": "Name",
"Value": {
"Value": "Acc 2",
"Values": [
"Acc 2"
]
}
},
{
"Key": "Id",
"Value": {
"Value": "2",
"Values": [
"2"
]
}
}
],
"Name": "account",
"Id": "2"
},
{
"Attributes": [
{
"Key": "Name",
"Value": {
"Value": "Acc 3",
"Values": [
"Acc 3"
]
}
},
{
"Key": "Id",
"Value": {
"Value": "3",
"Values": [
"3"
]
}
}
],
"Name": "account",
"Id": "2"
}
]
And I have these classes:
public class RetrieveMultipleResponse
{
public List<Attribute> Attributes { get; set; }
public string Name { get; set; }
public string Id { get; set; }
}
public class Value
{
[JsonProperty("Value")]
public string value { get; set; }
public List<string> Values { get; set; }
}
public class Attribute
{
public string Key { get; set; }
public Value Value { get; set; }
}
I am trying to deserialize the above JSON using the code below:
var objResponse1 = JsonConvert.DeserializeObject<RetrieveMultipleResponse>(JsonStr);
but I am getting this error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type
'test.Model.RetrieveMultipleResponse' because the type requires a JSON
object (e.g. {"name":"value"}) to deserialize correctly. To fix this
error either change the JSON to a JSON object (e.g. {"name":"value"})
or change the deserialized type to an array or a type that implements
a collection interface (e.g. ICollection, IList) like List that can
be deserialized from a JSON array. JsonArrayAttribute can also be
added to the type to force it to deserialize from a JSON array. Path
'', line 1, position 1.
Your json string is wrapped within square brackets ([]), hence it is interpreted as array instead of single RetrieveMultipleResponse object. Therefore, you need to deserialize it to type collection of RetrieveMultipleResponse, for example :
var objResponse1 =
JsonConvert.DeserializeObject<List<RetrieveMultipleResponse>>(JsonStr);
If one wants to support Generics (in an extension method) this is the pattern...
public static List<T> Deserialize<T>(this string SerializedJSONString)
{
var stuff = JsonConvert.DeserializeObject<List<T>>(SerializedJSONString);
return stuff;
}
It is used like this:
var rc = new MyHttpClient(URL);
//This response is the JSON Array (see posts above)
var response = rc.SendRequest();
var data = response.Deserialize<MyClassType>();
MyClassType looks like this (must match name value pairs of JSON array)
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class MyClassType
{
[JsonProperty(PropertyName = "Id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "Name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "Description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "Manager")]
public string Manager { get; set; }
[JsonProperty(PropertyName = "LastUpdate")]
public DateTime LastUpdate { get; set; }
}
Use NUGET to download Newtonsoft.Json add a reference where needed...
using Newtonsoft.Json;
Can't add a comment to the solution but that didn't work for me. The solution that worked for me was to use:
var des = (MyClass)Newtonsoft.Json.JsonConvert.DeserializeObject(response, typeof(MyClass));
return des.data.Count.ToString();
Deserializing JSON array into strongly typed .NET object
Use this, FrontData is JSON string:
var objResponse1 = JsonConvert.DeserializeObject<List<DataTransfer>>(FrontData);
and extract list:
var a = objResponse1[0];
var b = a.CustomerData;
To extract the first element (Key) try this method and it will be the same for the others :
using (var httpClient = new HttpClient())
{
using (var response = await httpClient.GetAsync("Your URL"))
{
var apiResponse = await response.Content.ReadAsStringAsync();
var list = JObject.Parse(apiResponse)["Attributes"].Select(el => new { Key= (string)el["Key"] }).ToList();
var Keys= list.Select(p => p.Key).ToList();
}
}
var objResponse1 =
JsonConvert.DeserializeObject<List<RetrieveMultipleResponse>>(JsonStr);
worked!
I got a JSON-File, that contains a various number of addresses.
Now I need a JSON-Schema to validate the complete JSON-File:
My JSON-File is looking similar to this:
[
{
"ID": "FIRST",
"Name" : "FirstName",
"ZIP" : "0815"
},
{
"ID": "SECOND",
"Name" : "SecondName",
"ZIP" : "4711"
},
{
"ID": "THIRD",
"Name" : "ThirdName",
"ZIP" : "123"
}
]
These are only three addresses, but the JSON-File can contain much more of them.
How has the Schema to look like?
I want to use the Schema-Generator to create the JSON-Schema!!!
Thanx for your help in advance.
Using newtonsoft Json.net.
You can generate the Schema from an object. doc
Your address class is simply :
public class Address
{
public string ID { get; set; }
public string Name { get; set; }
public string ZIP { get; set; }
}
The convertion will be :
using Newtonsoft.Json;
using Newtonsoft.Json.Schema;
JsonSchemaGenerator generator = new JsonSchemaGenerator();
JsonSchema schema = generator.Generate(typeof(Address[]));
Live Demo
You can use NJsonSchema Library (accessible via Nuget Packages) for generating schema from Json directly. For example,
var schema = JsonSchema.FromSampleJson(json);
var result = schema.ToJson();
Sample Output
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "array",
"items": {
"$ref": "#/definitions/Anonymous"
},
"definitions": {
"Anonymous": {
"type": "object",
"properties": {
"ID": {
"type": "string"
},
"Name": {
"type": "string"
},
"ZIP": {
"type": "string"
}
}
}
}
}
How do I create a JSON array using Newtonsoft.JSON (json.net) from this json string
[
{
"Cells": {
"results": [
{
"Key": "Title",
"Value": "hello",
"ValueType": "Edm.String"
},
{
"Key": "Size",
"Value": "54549",
"ValueType": "Edm.Int64"
},
{
"Key": "Path",
"Value": "http://somesite/a/hello.pptx",
"ValueType": "Edm.String"
},
{
"Key": "Summary",
"Value": "Some summary <ddd/> interesting reading <ddd/> nice book <ddd/> ",
"ValueType": "Edm.String"
},
{
"Key": "Name",
"Value": "http://somesite",
"ValueType": "Edm.String"
}
]
}
},
{
"Cells": {
"results": [
{
"Key": "Title",
"Value": "hi joe",
"ValueType": "Edm.String"
},
{
"Key": "Size",
"Value": "41234",
"ValueType": "Edm.Int64"
},
{
"Key": "Path",
"Value": "http://someothersite/interesting/hi.pptx",
"ValueType": "Edm.String"
},
{
"Key": "Summary",
"Value": "Some summary <ddd/> interesting reading <ddd/> nice book <ddd/> ",
"ValueType": "Edm.String"
},
{
"Key": "Name",
"Value": "http://somesite",
"ValueType": "Edm.String"
}
]
}
}
]
json2csharp gives me following classes for this structure
public class Result
{
public string Key { get; set; }
public string Value { get; set; }
public string ValueType { get; set; }
}
public class Cells
{
public List<Result> results { get; set; }
}
public class RootObject
{
public Cells Cells { get; set; }
}
How do I use these classes to create json array?
UPDATE AND SOLUTION
this will work
static void Main(string[] args)
{
RootObject ro = new RootObject();
Cells cs = new Cells();
cs.results = new List<Result>();
Result rt = new Result();
rt.Key = "Title";
rt.Value = "hello";
rt.ValueType = "Edm.String";
cs.results.Add(rt);
Result rs = new Result();
rs.Key = "Size";
rs.Value = "3223";
rs.ValueType = "Edm.Int64";
cs.results.Add(rs);
ro.Cells = cs;
string json = JsonConvert.SerializeObject(ro);
}
this will work
static void Main(string[] args)
{
RootObject ro = new RootObject();
Cells cs = new Cells();
cs.results = new List<Result>();
Result rt = new Result();
rt.Key = "Title";
rt.Value = "hello";
rt.ValueType = "Edm.String";
cs.results.Add(rt);
Result rs = new Result();
rs.Key = "Size";
rs.Value = "3223";
rs.ValueType = "Edm.Int64";
cs.results.Add(rs);
ro.Cells = cs;
string json = JsonConvert.SerializeObject(ro);
}
You're looking for the function DeserializeObject<T>:
var json = ""; // string up above in your code
var jObect = JsonConvert.DeserializeObject<RootObject>(json);
// Use
var cells = jObject.Cells;
var result1 = cells.results.FirstOrDefault();
Given an example of a POCO below:
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
This can be achieved by deserializing your JSON string show below:
string json = #"{
'Email': 'james#example.com',
'Active': true,
'CreatedDate': '2013-01-20T00:00:00Z',
'Roles': [
'User',
'Admin'
]
}";
Account account = JsonConvert.DeserializeObject<Account>(json);
Console.WriteLine(account.Email);
Reference Newtonsoft's documentation below:
http://www.newtonsoft.com/json/help/html/DeserializeObject.htm
If you want the string representation of an object, especially a json object, the most relevant is .ToString ().
But, it could fail for other reasons ...
In my service class constructor I populate two repositories:
private List<BackupRule> rules;
private List<BackupPath> paths;
public RuleService()
{
List<BackupRule> _rules = new List<BackupRule>();
List<BackupPath> _paths = new List<BackupPath>();
using (var wc = new System.Net.WebClient())
{
string json = wc.DownloadString(jsonRuleFile);
if (json.Length > 0)
{
_rules = JsonConvert.DeserializeObject<List<BackupRule>>(json);
_paths = JsonConvert.DeserializeObject<List<BackupPath>>(json);
}
}
rules = _rules;
paths = _paths;
}
Then I try to create a rule and add the rule to the repository:
code to create the rules
IRuleService db = new RuleService();
List<BackupPath> paths = new List<BackupPath>();
paths.Add(new BackupPath { Type = PathType.Source, Value = "C:\\Test\\" });
paths.Add(new BackupPath { Type = PathType.Destination, Value = "C:\\Test\\" });
paths.Add(new BackupPath { Type = PathType.Source, Value = "C:\\Test\\" });
paths.Add(new BackupPath { Type = PathType.Source, Value = "C:\\Test\\" });
BackupRule rule1 = new BackupRule() { Name = "test1", Type = RuleType.Archive, UserName = System.Environment.UserName, Paths = paths, EndOfDay = true, Created = DateTime.Now};
BackupRule rule2 = new BackupRule() { Name = "test2", Type = RuleType.Archive, UserName = System.Environment.UserName, Paths = paths, EndOfDay = true, Created = DateTime.Now };
db.CreateRule(rule1);
db.CreateRule(rule2);
db.SaveChanges();
Interface Methods that add the rules to the repositories
public BackupRule CreateRule(BackupRule rule)
{
if (rules.Any(r => r.Name == rule.Name))
{
return null;
}
rule.Paths = rule.Paths.OrderBy(p => p.Type.GetHashCode()).ToList();
foreach (BackupPath path in rule.Paths)
{
path.Id = (paths.Count() == 0) ? 1 : paths.LastOrDefault().Id + 1;
paths.Add(path);
}
rule.Id = (rules.Count() == 0) ? 1 : rules.LastOrDefault().Id + 1;
rules.Add(rule);
rules = rules.OrderBy(r => r.Id).ToList();
return rule;
}
Interface Method that serializes (sic?) back to json
public void SaveChanges()
{
using (FileStream fileStream = File.Open(#jsonRuleFile, FileMode.OpenOrCreate))
using (StreamWriter streamWriter = new StreamWriter(fileStream))
using (JsonWriter jsonWriter = new JsonTextWriter(streamWriter))
{
jsonWriter.Formatting = Formatting.Indented;
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(jsonWriter, rules);
serializer.Serialize(jsonWriter, paths);
}
}
json output
[
{
"Id": 1,
"Name": "test1",
"UserName": "Aaron",
"rule_type": "Archive",
"Paths": [
{
"$id": "1",
"Id": 5,
"Value": "C:\\Test\\",
"Type": "Source"
},
{
"$id": "2",
"Id": 6,
"Value": "C:\\Test\\",
"Type": "Source"
},
{
"$id": "3",
"Id": 7,
"Value": "C:\\Test\\",
"Type": "Source"
},
{
"$id": "4",
"Id": 8,
"Value": "C:\\Test\\",
"Type": "Destination"
}
],
"EndOfDay": true,
"Created": "2014-07-12T20:14:03.9126784-05:00"
},
{
"Id": 2,
"Name": "test2",
"UserName": "Aaron",
"rule_type": "Archive",
"Paths": [
{
"$ref": "1"
},
{
"$ref": "2"
},
{
"$ref": "3"
},
{
"$ref": "4"
}
],
"EndOfDay": true,
"Created": "2014-07-12T20:14:03.9126784-05:00"
}
][
{
"Id": 5,
"Value": "C:\\Test\\",
"Type": "Source"
},
{
"Id": 6,
"Value": "C:\\Test\\",
"Type": "Source"
},
{
"Id": 7,
"Value": "C:\\Test\\",
"Type": "Source"
},
{
"Id": 8,
"Value": "C:\\Test\\",
"Type": "Destination"
},
{
"Id": 5,
"Value": "C:\\Test\\",
"Type": "Source"
},
{
"Id": 6,
"Value": "C:\\Test\\",
"Type": "Source"
},
{
"Id": 7,
"Value": "C:\\Test\\",
"Type": "Source"
},
{
"Id": 8,
"Value": "C:\\Test\\",
"Type": "Destination"
}
]
Classes being serialized
// using statements added to post to help
// reader understand I am using Json.Net
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public class BackupRule
{
[JsonProperty]
public int Id { get; set; }
[JsonProperty]
public string Name { get; set; }
public string UserName { get; set; }
[JsonProperty(PropertyName = "rule_type")]
[JsonConverter(typeof(StringEnumConverter))]
public RuleType Type { get; set; }
[JsonProperty(ItemIsReference = true)]
public List<BackupPath> Paths { get; set; }
public bool EndOfDay { get; set; }
public DateTime Created { get; set; }
}
public class BackupPath
{
public int Id { get; set; }
public string Value { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public PathType Type { get; set; }
}
The problem(s) is the json isn't even a proper format it gives me:
Warning 1 Only one top-level array or object is allowed in a JSON document.
And it doesn't actually reference the serialized BackupPath class it just references other BackupPaths created in other BackupRule objects. Where did I go wrong here? Ideally I would like it to create two "tables" out of the lists and have the BackupRule reference the BackupPaths "table" much like it does in the second BackupRule example but instead of BackupRule #2 referencing BackupPath stored in BackupRule #1 I'd rather both reference the serialized BackupPath "table". Also ideally i'd like to store both of the serialized lists in one json file, but I am flexible on this.
As to the warning, that's because you have this:
serializer.Serialize(jsonWriter, rules);
serializer.Serialize(jsonWriter, paths);
As the warning says, JSON really can only have 1 top level element and you have written 2 top level elements. To make the warning go away, you could wrap rules and paths into a single object:
serializer.Serialize(jsonWriter, new {Rules = rules, Paths = paths});
I receive a JSON obejct to start a web session, using MVC4. I need to parse it into a C# object for later use. I cannot change the object I receive - it comes from a third party.
The method I am using to parse:
MyClass jsonObject = new MyClass();
//The 2 lines below will not work with the given answer
//JavaScriptSerializer serializer = new JavaScriptSerializer();
//jsonObject = serializer.Deserialize<MyClass >(jsonString);
//Use this method instead
jsonObject = JsonConvert.DeserializeObject<MyClass>(jsonString);
QUESTION:
I'm having trouble defining the C# class for this part of the JSON due to the "0" name of internal object.
JSON:
{
"header": {
"to": {
"data": [],
"0": {
"data": [],
"value": "1101",
"domain": "DUNS"
}
},
"from": {
"data": [],
"0": {
"data": [],
"value": "1101",
"domain": "NetworkID"
}
},
"sender": {
"data": {
"UserAgent": "Test Client v1"
},
"0": {
"data": {
"SharedSecret": "test"
},
"value": "testing#smith.com",
"domain": "testClientID"
}
}
},
...
}
NOTE: I have tried online json to C# class generators, either failure, or creating a class with a name '0' which of course does not compile.
Comments:
MyClass would be something like this:
public class Header
{
public ToClass to = new ToClass ();
public FromClass to = new FromClass ();
}
public class ToClass
{
public Data[];
public zero 0 = new zero();
}
public class zero
{
public string data { get; set; }
public string value { get; set; }
public string domain { get; set; }
}
I believe you can use json.NET's property attribute system to correct this, the docs are here.
http://james.newtonking.com/json/help/index.html?topic=html/SerializationAttributes.htm
public class ToClass
{
public Data[];
[JsonProperty(PropertyName = "0")]
public zero Zero = new zero();
}
This will make it so the deserializer equates the json property named 0 with the C# property named Zero