Deserializing Data From Facebook - c#

I am using Unity and the Facebook SDK.
Currently I am retrieving a list of users friends who have the app installed using the graph API:
The data when it is returned looks as such:
{
"data": [
{
"installed": true,
"id": "1292282928282"
},
{
"installed": true,
"id": "29282829292"
}
],
"paging": {
"next": "https://graph.facebook.com/v2.5/105157539862931/friends?fields=installed&format=json&access_token=CAALVPHznNpcBAOnO94HvqUgYKI2kObPZBgR0sqIOMSRO9swZBBTWHb6FjliZCT1KyCmPbnX42xvtngboh3DjFOrixw0pSenwRZA1oXZAHNDdYcGsHNOHjQcZB0f6fsZBQJjhOTttwQu7E5hZBDcAWJVZBGK2AxrZBDZBxLL7I5pjXwwbb12hDytZAiVzUmNzi1Ae2CCvOnL6QCpqzsJT7fWWjXXi&limit=25&offset=25&__after_id=enc_AdB7PJbXYkDSSZAq33AjPXZAeRnlrZBDwjAAILZAg3emHdei0qdRLa2AeD6sRuX6h0OQuPQi8x8bvSHPy0EqIgybYL89"
},
"summary": {
"total_count": 2
}
}
Currently I am trying to figure out how I can extract the "Installed" and id from each object inside of the "data" object.
so far I am doing this:
Dictionary<object,object> friendsList = Json.Deserialize (result.RawResult) as Dictionary<object,object>;
But I am not sure how I can pull out these specific items from the objects.
Does anyone know how I would go about doing this?

You need to have classes that will hold the deserialized data for you. For example create the following classes:
public class Datum
{
public bool installed { get; set; }
public string id { get; set; }
}
public class Paging
{
public string next { get; set; }
}
public class Summary
{
public int total_count { get; set; }
}
public class RootObject
{
public List<Datum> data { get; set; }
public Paging paging { get; set; }
public Summary summary { get; set; }
}
RootObject is the root class so the deserialization code will be:
var deserialized = Json.Deserialize<RootObject>(result.RawResult);
There is one more way to do it without creating classes, by using the dynamic keyword:
static void Main(string[] args)
{
var stringVal = #"{
""data"": [
{
""installed"": true,
""id"": ""1292282928282""
},
{
""installed"": true,
""id"": ""29282829292""
}
],
""paging"": {
""next"": ""https://graph.facebook.com/v2.5/105157539862931/friends? fields=installed&format=json&access_token=CAALVPHznNpcBAOnO94HvqUgYKI2kObPZBgR0sqIOMSRO9swZBBTWHb6FjliZCT1KyCmPbnX42xvtngboh3DjFOrixw0pSenwRZA1oXZAHNDdYcGsHNOHjQcZB0f6fsZBQJjhOTttwQu7E5hZBDcAWJVZBGK2AxrZBDZBxLL7I5pjXwwbb12hDytZAiVzUmNzi1Ae2CCvOnL6QCpqzsJT7fWWjXXi&limit=25&offset=25&__after_id=enc_AdB7PJbXYkDSSZAq33AjPXZAeRnlrZBDwjAAILZAg3emHdei0qdRLa2AeD6sRuX6h0OQuPQi8x8bvSHPy0EqIgybYL89""
},
""summary"": {
""total_count"": 2
}
}";
dynamic x = JsonConvert.DeserializeObject(stringVal);
var data = x.data;
foreach(var d in data)
{
bool installed = d.installed;
long id = d.id;
// todo: use the id and installed
}

Run this in Linqpad and you it will return the installed property.
void Main()
{
string jsonText =
#"{
""data"": [
{
""installed"": true,
""id"": ""1292282928282""
},
{
""installed"": true,
""id"": ""29282829292""
}
],
""paging"": {
""next"": ""https://graph.facebook.com/v2.5/105157539862931/friends?fields=installed&format=json&access_token=CAALVPHznNpcBAOnO94HvqUgYKI2kObPZBgR0sqIOMSRO9swZBBTWHb6FjliZCT1KyCmPbnX42xvtngboh3DjFOrixw0pSenwRZA1oXZAHNDdYcGsHNOHjQcZB0f6fsZBQJjhOTttwQu7E5hZBDcAWJVZBGK2AxrZBDZBxLL7I5pjXwwbb12hDytZAiVzUmNzi1Ae2CCvOnL6QCpqzsJT7fWWjXXi&limit=25&offset=25&__after_id=enc_AdB7PJbXYkDSSZAq33AjPXZAeRnlrZBDwjAAILZAg3emHdei0qdRLa2AeD6sRuX6h0OQuPQi8x8bvSHPy0EqIgybYL89""
},
""summary"": {
""total_count"": 2
}
}";
var x = JsonConvert.DeserializeObject<Response>(jsonText);
//To Get installed
x.data.Select(d => d.installed).Dump();
}
public class Response
{
public Data[] data;
public Paging paging;
public Summary summary;
}
public class Data
{
public bool installed { get; set; }
public string id { get; set; }
}
public class Paging
{
public string next { get; set; }
}
public class Summary
{
public int total_count { get; set;}
}

Consults this example for obtain a friend list using mini json:https://developers.facebook.com/docs/unity/reference/current/Json

Related

Deserializing my JSON into POCO not populating few fields

I have below json which I need to deserialize in C# -
{
"clientSettings":[
{
"clientId":12345,
"entries":[
{
"key":"abc",
"value":false
},
{
"key":"def",
"value":false
},
{
"key":"ghi",
"value":false
}
]
},
{
"clientId":9876,
"entries":[
{
"key":"lkmn",
"value":false
}
]
}
],
"productSettings":[
{
"productId":11,
"entries":[
{
"key":"jkl",
"value":true
},
{
"key":"mno",
"value":true
}
]
},
{
"productId":12,
"entries":[
{
"key":"jkl",
"value":true
},
{
"key":"mno",
"value":true
}
]
}
],
"customerSettings":[
{
"key":"enableData",
"value":false
},
{
"key":"minPriceValue",
"value":"10.28"
},
{
"key":"presentData",
"value":"AEGIS"
}
],
"thothTest":{
"9876":[
"K"
],
"5431":[
"A",
"L"
],
"5123":[
"L"
]
},
"osirisTest":{
"7678":[
"K"
]
}
}
Below is the classes I created to deserialzie json into -
public class ProcessHolder : Holder
{
public IDictionary<int, ISet<string>> OsirisTest { get; set; }
public IDictionary<int, ISet<string>> ThothTest { get; set; }
}
public class Holder
{
public IList<Mapping> CustomerSettings { get; set; }
public IList<ClientSettingsMapping> ClientSettings { get; set; }
public IList<ProductSettingsMapping> ProductSettings { get; set; }
}
public class Mapping
{
public string Key { get; set; }
public object Value { get; set; }
}
public class ProductSettingsMapping : Mapping
{
public int ProductId { get; set; }
}
public class ClientSettingsMapping : Mapping
{
public int ClientId { get; set; }
}
I want to load all customerSettings values into CustomerSettings object of Holder class.
Similarly I want to load all clientSettings values into ClientSettings object of Holder class.
Similarly all productSettings values into ProductSettings object of Holder class.
Similarly thothTest values into ThothTest and osirisTest values into OsirisTest object.
I was trying with below code but somehow I am not able to see Key and Value variables being populated inside Mapping class object after deserializing my above json.
private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
public static void Main(string[] args)
{
var jsonContent = File.ReadAllText("/beta/Downloads/test.json");
var config = JsonConvert.DeserializeObject<ProcessHolder>(jsonContent, serializerSettings);
if (config == null)
{
Console.WriteLine("Some Parsing Issue");
}
// using config object here
}
What is wrong I am doing here? I just need to deserialize my json into above classes and give me ProcessHolder object back which I can use later on.
Looking at your JSON, clientSettings and productSettings have entries array. There is no corresponding matching property in your class definition for same.
I would suggest to modify your class definition as per JSON. Try below and see if it helps:
public class ProductSettingsMapping
{
public int ProductId { get; set; }
public IList<Mapping> Entries { get; set; }
}
public class ClientSettingsMapping
{
public int ClientId { get; set; }
public IList<Mapping> Entries { get; set; }
}
Second option - if you are not able to modify classes, you can amend JSON. I am providing sample for clientSettings
{
"clientSettings": [
{
"clientId": 12345,
"key": "abc",
"value": false
},
{
"clientId": 12345,
"key": "def",
"value": false
},
{
"clientId": 12345,
"key": "ghi",
"value": false
},
{
"clientId": 9876,
"key": "lkmn",
"value": false
}
]
}
You can update productSettings accordingly.
Third option is to parse into JObject and then convert to your classes.
A sample for clientSettings
static void Main(string[] args)
{
var json = "{'clientSettings':[{'clientId':12345,'entries':[{'key':'abc','value':false},{'key':'def','value':false},{'key':'ghi','value':false}]},{'clientId':9876,'entries':[{'key':'lkmn','value':false}]}],'productSettings':[{'productId':11,'entries':[{'key':'jkl','value':true},{'key':'mno','value':true}]},{'productId':12,'entries':[{'key':'jkl','value':true},{'key':'mno','value':true}]}],'customerSettings':[{'key':'enableData','value':false},{'key':'minPriceValue','value':'10.28'},{'key':'presentData','value':'AEGIS'}],'thothTest':{'9876':['K'],'5431':['A','L'],'5123':['L']},'osirisTest':{'7678':['K']}}";
var parsed = JObject.Parse(json);
var parsedClientSettings = parsed["clientSettings"];
List<ClientSettingsMapping> clientSettings = new List<ClientSettingsMapping>();
foreach (var parsedClientSetting in parsedClientSettings)
{
var clientId = parsedClientSetting.Value<int>("clientId");
foreach (var entry in parsedClientSetting["entries"])
{
clientSettings.Add(new ClientSettingsMapping { ClientId = clientId, Key = entry["key"].ToString(), Value = entry["value"].ToString() });
}
}
ProcessHolder processHolder = new ProcessHolder() { ClientSettings = clientSettings };
Console.ReadLine();
}
You should define "entries" in both ProductSettingsMapping and ClientSettingsMapping class.
public class ProductSettingsMapping
{
public int ProductId { get; set; }
public IList<Mapping> entries { get; set; }
}
public class ClientSettingsMapping
{
public int ClientId { get; set; }
public IList<Mapping> entries { get; set; }
}

How to return ListAsync as an object

So currently this method gets the venuetype and outputs it's name, image and cafeID of that venue.
it's currently being returned as an Array, but I want to return it as an object but wasn't sure how to it's a simple question but I've been staring at it for a while now.
{
public class VenueTypeResponse
{
public string Name { get; set; }
public string ImageUrl { get; set; }
public int id { get; set; }
}
}
public VenueService(EVouchContext context)
{
_context = context;
}
//Gets venuetype and outputs the name, image and cafeID of that venue.
public async Task<List<VenueTypeResponse>> GetVenueType()
{
return await _context.CafeType.Select(s => new VenueTypeResponse()
{
id = s.CafeTypeId,
Name = s.Name,
ImageUrl = s.ImageUrl
}).ToListAsync();
}
I've tried the approach of removing the and returning it as .FirstorDefault but it clearly just returns the first venue type and not all of them. Any suggestions would be great! :)
Response I would like
{
data: [
{
id : 1,
name : "Take aways",
imageUrl : "https://..jpg"
},
{
id : 2,
name : "Desserts",
imageUrl : "https://..jpg"
},
{
...
},
{
...
}
],
meta: {
pageTotal: 1,
pageCurrent: 1
}
}
Response I'm getting
[
{
"name": "Restaurant",
"imageUrl": "https:..",
"id": 1
},
{
"name": "Takeaway",
"imageUrl": "https://...",
"id": 2
},
...
]
You need to create an object that holds your list, something like this:
public class Response
{
[JsonProperty("data")]
public List<VenueTypeResponse> Data { get; set; }
[JsonProperty("meta")]
public ResponseMeta Meta { get; set; }
}
public class ResponseMeta
{
[JsonProperty("pageTotal")]
public int PageTotal { get; set; }
[JsonProperty("pageCurrent")]
public int PageCurrent { get; set; }
}
and then either return this from your method, or wrap the result from this method into this object, before returning it from your endpoint.

Deserialize JSON array with unknown keys inside JSON object to a generic property - C#

Finding the right title for this problem was kinda hard so I'll try to explain the problem a bit better below.
I am making a call to an API which returns the following JSON object:
{{
"id": "jsonrpc",
"jsonrpc": "2.0",
"result": {
"result": [
{
"AccountId": 285929,
"Flags": [
"Managed_Obsolete"
],
"PartnerId": 73560,
"Settings": [
{
"AN": "company_1"
},
{
"CD": "1435323320"
},
{
"ED": "2147483647"
},
{
"OS": "Windows Server 2012 R2 Standard Edition (9600), 64-bit"
},
{
"OT": "2"
},
{
"T3": "1085792125772"
},
{
"US": "958222150780"
},
{
"YS": "100"
}
]
},
{
"AccountId": 610474,
"Flags": null,
"PartnerId": 249262,
"Settings": [
{
"AN": "company_2"
},
{
"CD": "1522143635"
},
{
"ED": "2147483647"
},
{
"OS": "Windows 7 Professional Service Pack 1 (7601), 64-bit"
},
{
"OT": "2"
},
{
"T3": "598346102236"
},
{
"US": "758149148249"
},
{
"YS": "100"
}
]
},
],
"totalStatistics": null
},
}}
In above result I listed only the first 2 accounts (total of 80+ accounts normally).
Deserializing the object works fine, I am putting the JSON object fields inside my C# model (list).
The problem however is that I can't get the (inner) Settings array properly in my model. The settings array keys are unknown, I define these keys when I call the API:
JObject requestObject = new JObject();
requestObject.Add(new JProperty("id", "jsonrpc"));
requestObject.Add(new JProperty("jsonrpc", "2.0"));
requestObject.Add(new JProperty("method", "myMethod"));
requestObject.Add(new JProperty("visa", someID));
requestObject.Add(new JProperty("params",
new JObject(
new JProperty("query", new JObject(
new JProperty("PartnerId", partnerId),
new JProperty("StartRecordNumber", 0),
new JProperty("RecordsCount", 9999999),
new JProperty("Columns", new JArray("AR", "AN", "US", "T3", "OT", "OS", "YS"))
)),
new JProperty("timeslice", unixDate),
new JProperty("totalStatistics", "*")
))
);
In above call I define the keys for the Settings array, this could however also be just one key or more. For this reason I want to make my Settings property in my C# model generic (I don't want to list all the possible key names because this are over 100 keys).
What I had so far:
List<EnumerateAccountHistoryStatisticsResult> resultList = new List<EnumerateAccountHistoryStatisticsResult>();
var result = JsonConvert.DeserializeObject<JObject>(streamreader.ReadToEnd());
dynamic innerResult = result["result"]["result"];
foreach (var obj in innerResult)
{
resultList.Add(
new EnumerateAccountHistoryStatisticsResult
{
AccountId = obj.AccountId,
Flags = obj.Flags.ToObject<IEnumerable<string>>(),
PartnerId = obj.PartnerId,
Settings = obj.Settings.ToObject<List<ColumnSettingsResult>>(),
});
}
The EnumerateAccountHistoryStatisticsResult Model:
public class EnumerateAccountHistoryStatisticsResult
{
public int AccountId { get; set; }
public IEnumerable<string> Flags { get; set; }
public int PartnerId { get; set; }
public List<ColumnSettingsResult> Settings { get; set; }
}
The ColumnSettingsResult model:
public class ColumnSettingsResult
{
public string AR { get; set; }
public string AN { get; set; }
public string US { get; set; }
public string T3 { get; set; }
public string OT { get; set; }
public string OS { get; set; }
public string YS { get; set; }
// and list all other columns...
}
With above models I would need to list all the possible columns which are over 100 properties, besides that the result of the Settings list is not logical because I get all the property values but for each different key I get null values:
The ColumnSettingsResult model should more be something like:
public class ColumnSettingsResult
{
public string ColumnName { get; set; }
public string ColumnValue { get; set; }
}
I cant get the key and value inside these two properties though without defining the key name inside the model..
I already tried several things without result (links below as reference).
Anyone that can get me in the right direction?
C# deserialize Json unknown keys
Convert JObject into Dictionary<string, object>. Is it possible?
Convert Newtonsoft.Json.Linq.JArray to a list of specific object type
Try making Settings of type Dictionary<string,string> (or List<KeyValuePair<string,string>> if Dictionary doesn't give you what you want.
public class MyJsonObject
{
public string id { get; set; }
public string jsonrpc { get; set; }
public Result result { get; set; }
public class Result2
{
public int AccountId { get; set; }
public List<string> Flags { get; set; }
public int PartnerId { get; set; }
public Dictionary<string,string> Settings { get; set; } //or List<KeyValuePair<string,string>>
}
public class Result
{
public List<Result2> result { get; set; }
public object totalStatistics { get; set; }
}
}
Then JsonConvert.DerserializeObject<MyJsonObject>(jsonString);

Newtonsoft JSON Deserialize AND jsonfreeze

I have a two simple PHP class
class Order{
public $orderNo;
public $lines = array();
public $paid = false;
public function addLine(OrderLine $line) {
$this->lines[] = $line;
}
public function setPaid($paid = true) {
$this->paid = true;
}
}
class OrderLine{
public function __construct($item, $amount){
$this->item = $item;
$this->amount = $amount;
}
public $item;
public $amount;
public $options;
}
Serialize object uses https://github.com/mindplay-dk/jsonfreeze
...
$json = new JsonSerializer;
$data = $json->serialize($order);
Have output:
{
"#type": "Order",
"orderNo": 123,
"lines": [{
"#type": "OrderLine",
"item": "milk \"fuzz\"",
"amount": 3,
"options": null
},{
"#type": "OrderLine",
"item": "cookies",
"amount": 7,
"options": {
"#type": "#hash",
"flavor": "chocolate",
"weight": "1\/2 lb"
}
}],
"paid": true
}
Send the string XMLRPC in VB.NET
As using Newtonsoft JSON get a live object?
As well as how to create a compatible format by analogy with the json string of living VB.net OR C# object?
Here's something you could start with. You create some classes with properties which represent the JSON Format (untested code, just as idea):
public class MyData
{
[JsonProperty("#type")]
public string Type { get; set; }
[JsonProperty("#orderNo")]
public int OrderNo { get; set;
[JsonProperty("paid")]
public bool Paid { get; set; }
[JsonProperty("lines")]
public List<MyDataLine> Lines { get; set; }
}
public class MyDataLines
{
[JsonProperty("#type")]
public string Type { get; set; }
[JsonProperty("options")]
public MyDataLinesOptions Options { get; set; }
// ... more
}
public class MyDataLinesOptions
{
// ... more
}
Then you can serialize and deserialize the the data like this:
string json = "the json data you received";
MyData myData = JsonConvert.DeserializeObject<MyData>(json);
// ...
json = JsonConvert.SerializeObject(myData);
"#type": "Order"
and
"#type": "OrderLine",
this is not a property, this is an indication of the type of the object

Failing to Parse Json to .NET class

Given:
The classes:
public class Venue
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("location")]
public Location Location { get; set; }
}
public class Location
{
public long Lat { get; set; }
public long Lng { get; set; }
public int Distance { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
public class Response
{
private List<Venue> _venues;
[JsonProperty("venues")]
public List<Venue> Venues
{
get { return _venues ?? (_venues = new List<Venue>()); }
set { _venues = value; }
}
}
And a response request:
{
"meta":{
"code":200
},
"response":{
"venues":[
{
"id":"4f96a5aee4b01cb74e4dc3c6",
"name":"Centro",
"contact":{
},
"location":{
"address":"Centro",
"lat":-21.256906640441052,
"lng":-48.31978432813259,
"distance":185,
"city":"Jaboticabal",
"state":"SP",
"country":"Brazil",
"cc":"BR"
},
"canonicalUrl":"https:\/\/foursquare.com\/v\/centro\/4f96a5aee4b01cb74e4dc3c6",
"categories":[
{
"id":"4f2a25ac4b909258e854f55f",
"name":"Neighborhood",
"pluralName":"Neighborhoods",
"shortName":"Neighborhood",
"icon":{
"prefix":"https:\/\/foursquare.com\/img\/categories_v2\/parks_outdoors\/neighborhood_",
"suffix":".png"
},
"primary":true
}
],
"verified":false,
"restricted":true,
"stats":{
"checkinsCount":1106,
"usersCount":86,
"tipCount":0
},
"specials":{
"count":0,
"items":[
]
},
"hereNow":{
"count":0,
"groups":[
]
},
"referralId":"v-1376511204"
},
{
"id":"4c38b0b21a38ef3b56b39221",
"name":"Ice by Nice",
"contact":{
},
"location":{
"address":"Jaboticabal Shopping",
"lat":-21.25513775,
"lng":-48.32320093,
"distance":253,
"city":"Jaboticabal",
"state":"SP",
"country":"Brazil",
"cc":"BR"
},
"canonicalUrl":"https:\/\/foursquare.com\/v\/ice-by-nice\/4c38b0b21a38ef3b56b39221",
"categories":[
{
"id":"4bf58dd8d48988d1c9941735",
"name":"Ice Cream Shop",
"pluralName":"Ice Cream Shops",
"shortName":"Ice Cream",
"icon":{
"prefix":"https:\/\/foursquare.com\/img\/categories_v2\/food\/icecream_",
"suffix":".png"
},
"primary":true
}
],
"verified":false,
"restricted":true,
"stats":{
"checkinsCount":656,
"usersCount":309,
"tipCount":15
},
"specials":{
"count":0,
"items":[
]
},
"hereNow":{
"count":2,
"groups":[
{
"type":"others",
"name":"Other people here",
"count":2,
"items":[
]
}
]
},
"referralId":"v-1376511204"
}
]
}
}
When using JSON.NET like so:
Response response = JsonConvert.DeserializeObject<Response>(jsonString);
The deserialized response object has a empty list of venues, What am I doing wrong?
Thanks
There's a bit of a mismatch in what you're trying to deserialize and the class you have defined to deserialize into. You unfortunately need yet another layer of indirection. Note the response has;
// theres an outer object here which contains response
{
"meta":{ "code":200 },
"response":{
// you're trying to deserialize this, but it's not the entire response, it's a property of an anonymous object
}
}
So if I make a new class;
public class ResponseWrapper
{
public object meta;
public Response response;
}
And instead do;
ResponseWrapper response = JsonConvert.DeserializeObject<ResponseWrapper>(jsonString);
Then it will work.
Note that when you're deserializing using json.NET you have to define a structure that exactly matches the json. In this case you're leaving out the outer most object. It is kind of an annoyance and leads to a lot of code like what I just wrote but that's just the way it goes sometimes.

Categories