This question already has answers here:
Serialize and Deserialize Json and Json Array in Unity
(9 answers)
Closed 5 years ago.
I have some problems with converting a json string into a c# List!
This is my JSON that i get from form a server.
[
{"roundid":1,"coins":700,"created":"2016-03-16 11:13:26","duration":198,"score":765230},
{"roundid":3,"coins":330,"created":"2016-03-16 11:13:56","duration":123,"score":425726},
{"roundid":4,"coins":657,"created":"2016-03-16 11:21:23","duration":432,"score":75384},
{"roundid":8,"coins":980,"created":"2016-03-16 11:23:19","duration":271,"score":827200}
]
In my C# program i then try to transform my json string into useable objects using with this function
public List<Round> getPlayerRounds(string username)
{
string url = BaseURL + "op=findUserRounds&username=" + username;
var json = new WebClient().DownloadString(url);
RoundDataList rounds = JsonUtility.FromJson<RoundDataList>(json);
List<Round> playerRounds = new List<Round>();
//for (var i = 0; i < rounds.roundList.Count; i++)
for (var i = 0; i < rounds.roundList.Length; i++)
{
RoundData rd = rounds.roundList[i];
Round r = rd.getRound();
playerRounds.Add(r);
}
return playerRounds;
}
Here i get error
ArgumentException: JSON must represent an object type.
I've looked around and haven't found anything that works, Tried 2-3 solution even tried edited my php webservice that creates the JSON string.
My Classes looks like this
/* This is previus atempt to solve the issue
[Serializable]
public class RoundDataList
{
public List<RoundData> roundList;
}
*/
[Serializable]
public class RoundDataList
{
public RoundData[] roundList;
}
[Serializable]
public class RoundData
{
public int roundid;
public int coins;
public DateTime created;
public int duration;
public int score;
public Round getRound()
{
Round r = new Round();
r.Roundid = roundid;
r.Coins = coins;
r.Created = created;
r.Duration = duration;
r.Score = score;
return r;
}
}
Thank for looking at this long post!
Unity's new Json API does not support Json array and that is exactly what your problem is. There is a way to do it but it is a long process to repost again. Just read how to do it here.What you are looking for is the second solution that says "2. MULTIPLE DATA(ARRAY JSON)."
Creating a class and another class holding list of it works for me.
[Serializable]
public class Questions
{
public string id;
public string question;
public string answer1;
public string answer2;
}
[Serializable]
public class QuestionList
{
public List<Questions> list;
}
//and
var jstring = "{\"list\":[{\"id\":\"1\",\"question\":\"lorem Ipsome \",\"answer1\":\"yes\",\"answer2\":\"no\"},{\"id\":\"2\",\"question\":\"lorem Ipsome Sit dore iman\",\"answer1\":\"si\",\"answer2\":\"ne\"}]}";
var result = JsonUtility.FromJson<QuestionList>(jstring);
From a list, Convert to JSON
List<Questions> questionlist = new List<Questions>();
questionlist.Add(new Questions()
{
answer1 = "yes",
answer2 = "no",
id = "1",
question = "lorem Ipsome "
});
questionlist.Add(new Questions()
{
answer1 = "si",
answer2 = "ne",
id = "2",
question = "lorem Ipsome Sit dore iman"
});
var ql = new QuestionList();
ql.list = questionlist;
var result = JsonUtility.ToJson(ql);
//this gives
{"list":[{"id":"1","question":"lorem Ipsome ","answer1":"yes","answer2":"no"},{"id":"2","question":"lorem Ipsome Sit dore iman","answer1":"si","answer2":"ne"}]}
Note: "list" and questionList.list should be in same name.
Related
Can somebody help me to parse the json and get the details.
Lets say i have Top2 input parameter as Police and i want to know the respective Top3 and in that Top3 array i need to check whether Test1Child value is there or not.
I am using newtonsoft json + c# and so far i can get till DeviceTypes using below code
var json = File.ReadAllText(jsonFile); // below json is stored in file jsonFile
var jObject = JObject.Parse(json);
JArray MappingArray =(JArray)jObject["Top1"];
string strTop1 = ObjZone.Top1.ToString();
string strTop2 = ObjZone.Top2.ToString();
var JToken = MappingArray.Where(obj => obj["Top2"].Value<string>() == strTop2).ToList();
//Json
{
"Top1": [
{
"Top2": "Test1",
"Top3": [
"Test1Child"
]
},
{
"Top2": "Test2",
"Top3": [
"Test2Child"
]
}
]
}
I'd use http://json2csharp.com/ (or any other json to c# parser) and then use C# objects (it's just easier for me)
This would look like that for this case:
namespace jsonTests
{
public class DeviceTypeWithResponseTypeMapper
{
public string DeviceType { get; set; }
public List<string> ResponseTypes { get; set; }
}
public class RootObject
{
public List<DeviceTypeWithResponseTypeMapper> DeviceTypeWithResponseTypeMapper { get; set; }
}
}
and the use it like that in code:
var rootob = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(str);
var thoseThatHaveNotUsed = rootob.DeviceTypeWithResponseTypeMapper.Where(dtwrtm =>
dtwrtm.ResponseTypes.Any(rt => rt == "NotUsed"));
foreach (var one in thoseThatHaveNotUsed)
{
Console.WriteLine(one.DeviceType);
}
this code lists all the Device types that have "NotUsed" among the responses.
version 2 (extending your code) would look like that, i believe:
static void Main(string[] args)
{
var json = str; // below json is stored in file jsonFile
var jObject = JObject.Parse(json);
JArray ZoneMappingArray = (JArray)jObject["DeviceTypeWithResponseTypeMapper"];
string strDeviceType = "Police";
string strResponseType = "NotUsed";
var JToken = ZoneMappingArray.Where(obj => obj["DeviceType"].Value<string>() == strDeviceType).ToList();
var isrespTypeThere = JToken[0].Last().Values().Any(x => x.Value<string>() == strResponseType);
Console.WriteLine($"Does {strDeviceType} have response type with value {strResponseType}? {yesorno(isrespTypeThere)}");
}
private static object yesorno(bool isrespTypeThere)
{
if (isrespTypeThere)
{
return "yes!";
}
else
{
return "no :(";
}
}
result:
and if you'd like to list all devices that have response type equal to wanted you can use this code:
var allWithResponseType = ZoneMappingArray.Where(jt => jt.Last().Values().Any(x => x.Value<string>() == strResponseType));
foreach (var item in allWithResponseType)
{
Console.WriteLine(item["DeviceType"].Value<string>());
}
I have a JsonString:
"baseAbilities":"[{"baseId":1,"name":"Focused Elemental Strike"}]"
I want to make it:
"baseAbilities":[{"baseId":1,"name":"Focused Elemental Strike"}]
So the it is easy for JSON utility to deserialise it. Any suggestions
EDIT:
This is basically a json object in the following Json String:
{"data”: [{"id":9,"name":"Sam5","baseAbilities":"[{\"baseId\":1,\"name\":\"Focused Elemental Strike\"},{\"baseId\":9,\"name\":\"Cleanse\"}]"]}
The backend developer saved JSON in a column baseAbilities as a string. Now I don't have the access to Back end APIs. So i need to convert this string baseAbilities to JSON so that I can access objects inside it.
Now I use these classes to decode JSON:
[System.Serializable]
class GetBAResult
{
public List<bounceAbilityData> data;
}
[System.Serializable]
class bounceAbilityData
{
public int id;
public string name;
public string baseAbilities;
}
And this is how I decode JSON:
GetBAResult P = JsonUtility.FromJson<GetBAResult>(w.text);
for (int i = 0; i < P.data.Count; i++)
{
Debug.Log(P.data[i].name);
GameObject layoutGroupNameButton = (GameObject)Instantiate(prefabBAButton);
layoutGroupNameButton.transform.SetParent(ParentPanel, false);
layoutGroupNameButton.GetComponentInChildren<Text>().text = P.data[i].name;
layoutGroupNameButton.GetComponent<BounceAbilityButton>().id = P.data[i].id;
layoutGroupNameButton.GetComponent<BounceAbilityButton>().name = P.data[i].name;
Debug.Log(P.data[i].baseAbilities);
}
I need to get things inside baseAbilities such as "baseID" and "name"
Have you tried this?
JObject json = JObject.Parse(str);
documentation
With a class set of
[System.Serializable]
class GetBAResult
{
public List<bounceAbilityData> data;
}
[System.Serializable]
class bounceAbilityData
{
public int id;
public string name;
public List<BaseAbilities> baseAbilities;
}
[System.Serializable]
class BaseAbilities
{
public int baseId;
public string name;
}
You can then use the following to Deserialize your JSON to an instance of GetBAResult
string json = "{\"data\":[{\"id\":9,\"name\":\"Sam5\",\"baseAbilities\":[{\"baseId\":1,\"name\":\"Focused Elemental Strike\"},{\"baseId\":9,\"name\":\"Cleanse\"}]}]}";
GetBAResult myObject = JsonUtility.FromJson<GetBAResult>(json);
BaseAbilities abilities = myObject.data[0].baseAbilities[0];
You can read more about JSON Deserialization here on the Unity Documentation
https://docs.unity3d.com/Manual/JSONSerialization.html
The original questions says that you want to change:
"baseAbilities":"[{"baseId":1,"name":"Focused Elemental Strike"}]"
to
"baseAbilities":[{"baseId":1,"name":"Focused Elemental Strike"}]
Basically, you want to remove the " before the [{" then remove the final " at the end of the json string. The problem is that even after you do this, "baseAbilities":[{"baseId":1,"name":"Focused Elemental Strike"}] cannot be serialized to json.
You need to add { in front of it and } at the end of it.
The final string after adding { in front of it and } at the end is:
{"baseAbilities":[{"baseId":1,"name":"Focused Elemental Strike"}]}
The fixJson function below fixes those problems and this is how to use it:
[System.Serializable]
public class BaseAbility
{
public int id;
public string name;
}
[System.Serializable]
public class GetBAResult
{
public List<BaseAbility> baseAbilities;
}
void Start()
{
// StartCoroutine(RespawnPlayer());
string fixedJson = fixJson(w.text);
//string fixedJson = fixJson("\"baseAbilities\":\"[{\"id\":1,\"name\":\"Focused Elemental Strike\"}]\"");
Debug.Log("Fixed Json: " + fixedJson);
GetBAResult P = JsonUtility.FromJson<GetBAResult>(fixedJson);
Debug.Log("Count Json: " + P.baseAbilities.Count);
for (int i = 0; i < P.baseAbilities.Count; i++)
{
Debug.Log("Name: " + P.baseAbilities[i].name);
Debug.Log("Base ID: " + P.baseAbilities[i].id);
}
}
string fixJson(string jsonToFix)
{
//First srting with `"` that will be removed
const string firstString = "\"baseAbilities\":\"";
//Last string with `"` that will be removed
const string lastString = "\"";
//String that will be used to fix the "baseAbilities":"[ with the `"`
const string fixedFirstString = "\"baseAbilities\":";
//Get the first Index of firstString
int firstIndex = jsonToFix.IndexOf(firstString);
//Remove First Index of `firstString`
jsonToFix = jsonToFix.Remove(firstIndex, firstString.Length);
int lastIndex = jsonToFix.LastIndexOf(lastString);
//Remove everything from Last `lastString` to the end
jsonToFix = jsonToFix.Remove(lastIndex);
//Append the correct/fixed string without `"` to the beginning of the json data
jsonToFix = fixedFirstString + jsonToFix;
//Add `{` to the begging and `}` to the end of the json data
jsonToFix = "{" + jsonToFix + "}";
return jsonToFix;
}
Let's say you have a class like this:
using System;
using System.Collections.Generic;
using UnityEngine;
public class JsonTest : MonoBehaviour
{
[Serializable]
public class Ability
{
public int baseId;
public string name;
public Ability(int _baseId, string _name)
{
baseId = _baseId;
name = _name;
}
}
public class Abilities
{
public List<Ability> baseAbilities;
public Abilities(List<Ability> _baseAbilities)
{
baseAbilities = _baseAbilities;
}
}
void Start()
{
List<Ability> list = new List<Ability>();
list.Add(new Ability(1, "Focused Elemental Strike"));
list.Add(new Ability(2, "Another ability"));
Abilities baseAbilities = new Abilities(list);
string serializedAbilites = JsonUtility.ToJson(baseAbilities);
Debug.Log(serializedAbilites);
Abilities deserializedAbilites = JsonUtility.FromJson<Abilities>(serializedAbilites);
}
}
You have an Ability class marked as Serializable containing and id and a name.
You have another class Abilities used as a wrapper for a list of abilities.
You can then serialize a list of abilities using JsonUtility.ToJson(). Which will give you the following string:
{
"baseAbilities": [
{
"baseId": 1,
"name": "Focused Elemental Strike"
},
{
"baseId": 2,
"name": "Another ability"
}
]
}
And of course you can deserialize it using JsonUtility.FromJson().
Is this what your looking for ?
I am making a Quiz/Trivia Game and have questions stored in XML file and it gets a random question. Everything works fine, but I want to stay random but not show the same question until every question has been shown.
public struct Question {
public string questionText;
public string answerA;
public string answerB;
public string answerC;
public string answerD;
public int correctAnswerID;
}
[XmlRoot("QuestionsRoot")]
public class QuestionData {
[XmlArray("Questions")]
[XmlArrayItem("Question")]
public List<Question>questions = new List<Question>();
public static QuestionData LoadFromText(string text) {
try {
XmlSerializer serializer = new XmlSerializer(typeof(QuestionData));
return serializer.Deserialize(new StringReader(text)) as QuestionData;
} catch (Exception e) {
UnityEngine.Debug.LogError("Exception loading question data: " + e);
return null;
}
}
And I use this in my other script to get a random question:
questionData = QuestionData.LoadFromText(questionDataXMLFile.text)
q = Random.Range(0, questionData.questions.Count);
currentQuestion = questionData.questions[q];
Do something along the following lines:
create another list with available questions - initialise it to the list of all questions:
questionData = QuestionData.LoadFromText(questionDataXMLFile.text)
var available = new List<Question>(questionData.question);
...
}
public Question GetNextQuestion()
{
if (available.Count == 0)
available.AddRange(questionData.question);
q = Random.Range(0, available.Count);
currentQuestion = available[q];
available.RemoveAt(q);
return currentQuestion;
}
Trying to convert a JSON string into an object in C#. Using a really simple test case:
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
object routes_list = json_serializer.DeserializeObject("{ \"test\":\"some data\" }");
The problem is that routes_list never gets set; it's an undefined object. Any ideas?
Or, you can use the Newtownsoft.Json library as follows:
using Newtonsoft.Json;
...
var result = JsonConvert.DeserializeObject<T>(json);
Where T is your object type that matches your JSON string.
It looks like you're trying to deserialize to a raw object. You could create a Class that represents the object that you're converting to. This would be most useful in cases where you're dealing with larger objects or JSON Strings.
For instance:
class Test {
String test;
String getTest() { return test; }
void setTest(String test) { this.test = test; }
}
Then your deserialization code would be:
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
Test routes_list =
(Test)json_serializer.DeserializeObject("{ \"test\":\"some data\" }");
More information can be found in this tutorial:
http://www.codeproject.com/Tips/79435/Deserialize-JSON-with-Csharp.aspx
You probably don't want to just declare routes_list as an object type. It doesn't have a .test property, so you really aren't going to get a nice object back. This is one of those places where you would be better off defining a class or a struct, or make use of the dynamic keyword.
If you really want this code to work as you have it, you'll need to know that the object returned by DeserializeObject is a generic dictionary of string,object. Here's the code to do it that way:
var json_serializer = new JavaScriptSerializer();
var routes_list = (IDictionary<string, object>)json_serializer.DeserializeObject("{ \"test\":\"some data\" }");
Console.WriteLine(routes_list["test"]);
If you want to use the dynamic keyword, you can read how here.
If you declare a class or struct, you can call Deserialize instead of DeserializeObject like so:
class MyProgram {
struct MyObj {
public string test { get; set; }
}
static void Main(string[] args) {
var json_serializer = new JavaScriptSerializer();
MyObj routes_list = json_serializer.Deserialize<MyObj>("{ \"test\":\"some data\" }");
Console.WriteLine(routes_list.test);
Console.WriteLine("Done...");
Console.ReadKey(true);
}
}
Using dynamic object with JavaScriptSerializer.
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>("{ \"test\":\"some data\" }");
string test= item["test"];
//test Result = "some data"
Newtonsoft is faster than java script serializer. ... this one depends on the Newtonsoft NuGet package, which is popular and better than the default serializer.
one line code solution.
var myclass = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(Jsonstring);
Myclass oMyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<Myclass>(Jsonstring);
You can accomplished your requirement easily by using Newtonsoft.Json library. I am writing down the one example below have a look into it.
Class for the type of object you receive:
public class User
{
public int ID { get; set; }
public string Name { get; set; }
}
Code:
static void Main(string[] args)
{
string json = "{\"ID\": 1, \"Name\": \"Abdullah\"}";
User user = JsonConvert.DeserializeObject<User>(json);
Console.ReadKey();
}
this is a very simple way to parse your json.
Here's a simple class I cobbled together from various posts.... It's been tested for about 15 minutes, but seems to work for my purposes. It uses JavascriptSerializer to do the work, which can be referenced in your app using the info detailed in this post.
The below code can be run in LinqPad to test it out by:
Right clicking on your script tab in LinqPad, and choosing "Query
Properties"
Referencing the "System.Web.Extensions.dll" in "Additional References"
Adding an "Additional Namespace Imports" of
"System.Web.Script.Serialization".
Hope it helps!
void Main()
{
string json = #"
{
'glossary':
{
'title': 'example glossary',
'GlossDiv':
{
'title': 'S',
'GlossList':
{
'GlossEntry':
{
'ID': 'SGML',
'ItemNumber': 2,
'SortAs': 'SGML',
'GlossTerm': 'Standard Generalized Markup Language',
'Acronym': 'SGML',
'Abbrev': 'ISO 8879:1986',
'GlossDef':
{
'para': 'A meta-markup language, used to create markup languages such as DocBook.',
'GlossSeeAlso': ['GML', 'XML']
},
'GlossSee': 'markup'
}
}
}
}
}
";
var d = new JsonDeserializer(json);
d.GetString("glossary.title").Dump();
d.GetString("glossary.GlossDiv.title").Dump();
d.GetString("glossary.GlossDiv.GlossList.GlossEntry.ID").Dump();
d.GetInt("glossary.GlossDiv.GlossList.GlossEntry.ItemNumber").Dump();
d.GetObject("glossary.GlossDiv.GlossList.GlossEntry.GlossDef").Dump();
d.GetObject("glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso").Dump();
d.GetObject("Some Path That Doesnt Exist.Or.Another").Dump();
}
// Define other methods and classes here
public class JsonDeserializer
{
private IDictionary<string, object> jsonData { get; set; }
public JsonDeserializer(string json)
{
var json_serializer = new JavaScriptSerializer();
jsonData = (IDictionary<string, object>)json_serializer.DeserializeObject(json);
}
public string GetString(string path)
{
return (string) GetObject(path);
}
public int? GetInt(string path)
{
int? result = null;
object o = GetObject(path);
if (o == null)
{
return result;
}
if (o is string)
{
result = Int32.Parse((string)o);
}
else
{
result = (Int32) o;
}
return result;
}
public object GetObject(string path)
{
object result = null;
var curr = jsonData;
var paths = path.Split('.');
var pathCount = paths.Count();
try
{
for (int i = 0; i < pathCount; i++)
{
var key = paths[i];
if (i == (pathCount - 1))
{
result = curr[key];
}
else
{
curr = (IDictionary<string, object>)curr[key];
}
}
}
catch
{
// Probably means an invalid path (ie object doesn't exist)
}
return result;
}
}
As tripletdad99 said
var result = JsonConvert.DeserializeObject<T>(json);
but if you don't want to create an extra object you can make it with Dictionary instead
var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(json_serializer);
add this ddl to reference to your project: System.Web.Extensions.dll
use this namespace: using System.Web.Script.Serialization;
public class IdName
{
public int Id { get; set; }
public string Name { get; set; }
}
string jsonStringSingle = "{'Id': 1, 'Name':'Thulasi Ram.S'}".Replace("'", "\"");
var entity = new JavaScriptSerializer().Deserialize<IdName>(jsonStringSingle);
string jsonStringCollection = "[{'Id': 2, 'Name':'Thulasi Ram.S'},{'Id': 2, 'Name':'Raja Ram.S'},{'Id': 3, 'Name':'Ram.S'}]".Replace("'", "\"");
var collection = new JavaScriptSerializer().Deserialize<IEnumerable<IdName>>(jsonStringCollection);
Copy your Json and paste at textbox on json2csharp and click on Generate button.
A cs class will be generated use that cs file as below
var generatedcsResponce = JsonConvert.DeserializeObject(yourJson);
Where RootObject is the name of the generated cs file;
Another fast and easy way to semi-automate these steps is to:
take the JSON you want to parse and paste it here: https://app.quicktype.io/ . Change language to C# in the drop down.
Update the name in the top left to your class name, it defaults to "Welcome".
In visual studio go to Website -> Manage Packages and use NuGet to add Json.Net from Newtonsoft.
app.quicktype.io generated serialize methods based on Newtonsoft.
Alternatively, you can now use code like:
WebClient client = new WebClient();
string myJSON = client.DownloadString("https://URL_FOR_JSON.com/JSON_STUFF");
var myClass = Newtonsoft.Json.JsonConvert.DeserializeObject(myJSON);
Convert a JSON string into an object in C#. Using below test case.. its worked for me. Here "MenuInfo" is my C# class object.
JsonTextReader reader = null;
try
{
WebClient webClient = new WebClient();
JObject result = JObject.Parse(webClient.DownloadString("YOUR URL"));
reader = new JsonTextReader(new System.IO.StringReader(result.ToString()));
reader.SupportMultipleContent = true;
}
catch(Exception)
{}
JsonSerializer serializer = new JsonSerializer();
MenuInfo menuInfo = serializer.Deserialize<MenuInfo>(reader);
First you have to include library like:
using System.Runtime.Serialization.Json;
DataContractJsonSerializer desc = new DataContractJsonSerializer(typeof(BlogSite));
string json = "{\"Description\":\"Share knowledge\",\"Name\":\"zahid\"}";
using (var ms = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(json)))
{
BlogSite b = (BlogSite)desc.ReadObject(ms);
Console.WriteLine(b.Name);
Console.WriteLine(b.Description);
}
Let's assume you have a class name Student it has following fields and it has a method which will take JSON as a input and return a string Student Object.We can use JavaScriptSerializer here Convert JSON String To C# Object.std is a JSON string here.
public class Student
{
public string FirstName {get;set:}
public string LastName {get;set:}
public int[] Grades {get;set:}
}
public static Student ConvertToStudent(string std)
{
var serializer = new JavaScriptSerializer();
Return serializer.Deserialize<Student>(std);
}
Or, you can use the System.Text.Json library as follows:
using System.Text.Json;
...
var options = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
});
var result = JsonSerializer.Deserialize<List<T>>(json, options);
Where T is your object type that matches your JSON string.
System.Text.Json is available in:
.NET Core 2.0 and above
.NET Framework 4.6.1 and above
My code is below. I am not able to extract the 'name' and 'query' lists
from the JSON via a DataContracted Class (below)
I have spent a long time trying to work this one out, and could really do
with some help...
My Json string:
{"as_of":1266853488,"trends":{"2010-02-22
15:44:48":[{"name":"#nowplaying","query":"#nowplaying"},{"name":"#musicmonday","query":"#musicmonday"},{"name":"#WeGoTogetherLike","query":"#WeGoTogetherLike"},{"name":"#imcurious","query":"#imcurious"},{"name":"#mm","query":"#mm"},{"name":"#HumanoidCityTour","query":"#HumanoidCityTour"},{"name":"#awesomeindianthings","query":"#awesomeindianthings"},{"name":"#officeformac","query":"#officeformac"},{"name":"Justin
Bieber","query":"\"Justin Bieber\""},{"name":"National
Margarita","query":"\"National Margarita\""}]}}
My code:
WebClient wc = new WebClient();
wc.Credentials = new NetworkCredential(this.Auth.UserName, this.Auth.Password);
string res = wc.DownloadString(new Uri(link));
//the download string gives me the above JSON string - no problems
Trends trends = new Trends();
Trends obj = Deserialise<Trends>(res);
private T Deserialise<T>(string json)
{
T obj = Activator.CreateInstance<T>();
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
DataContractJsonSerializer serialiser = new DataContractJsonSerializer(obj.GetType());
obj = (T)serialiser.ReadObject(ms);
ms.Close();
return obj;
}
}
[DataContract]
public class Trends
{
[DataMember(Name = "as_of")]
public string AsOf { get; set; }
//The As_OF value is returned - But how do I get the
//multidimensional array of Names and Queries from the JSON here?
}
I've run into this very issue while developing Twitterizer. The issue is that the dataset isn't in a traditional object-oriented design.
If you were to map that as objects, you would see:
object root
int as_of
object trends
array[object] <date value of as_of>
string query
string name
As you can see, the trend object has a property that's name changes. The name is based on the as_of date value. As such, it can't be automatically deserialized.
My first solution was to use System.Web.Script.Serialization.JavaScriptSerializer.DeserializeObject(). That method returns a hierarchy of weakly typed, nested dictionary instances. I then stepped through the results myself.
internal static TwitterTrendTimeframe ConvertWeakTrend(object value)
{
Dictionary<string, object> valueDictionary = (Dictionary<string, object>)value;
DateTime date = new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds((int)valueDictionary["as_of"]);
object[] trends = (object[])((Dictionary<string, object>)valueDictionary["trends"])[date.ToString("yyyy-MM-dd HH:mm:ss")];
TwitterTrendTimeframe convertedResult = new TwitterTrendTimeframe()
{
EffectiveDate = date,
Trends = new Collection<TwitterTrend>()
};
for (int i = 0; i < trends.Length; i++)
{
Dictionary<string, object> item = (Dictionary<string, object>)trends[i];
TwitterTrend trend = new TwitterTrend()
{
Name = (string)item["name"]
};
if (item.ContainsKey("url"))
{
trend.Address = (string)item["url"];
}
if (item.ContainsKey("query"))
{
trend.SearchQuery = (string)item["query"];
}
convertedResult.Trends.Add(trend);
}
return convertedResult;
}
It's ugly, but it worked.
I've since embraced the use of Json.NET for it's speed and simplicity.
have you considered using JSON.net ?
Consider this example:
public struct TwitterResponse
{
public int32 as_of;
public Trend[] Trends;
}
public struct Trends
{
public String name;
public String query;
}
Trend[] obj = JavaScriptConvert.DeserializeObject<TwitterResponse>( res ).Trends;
Probably needs finetuning, but that's the general idea on how to do it.