I'm trying to process a JSON structure with Json.NET and encountered some issues:
My classes don't work when a JSON contains an unnamed array.
Json Example:
{
"graph_property" : [{
"name" : "calculation_method",
"value" : "Arithmetic"
}, {
"name" : "graph_type",
"value" : "TIME"
}
],
"measurement" : [{
"id" : "9997666",
"alias" : "Measurement (TxP)[IE]-Home Page - Total Time (seconds)",
"bucket_data" : [{
"name" : "2013-MAR-18 12:00 AM",
"id" : 1,
"perf_data" : {
"value" : "2.244",
"unit" : "seconds"
},
"avail_data" : {
"value" : "99.67",
"unit" : "percent"
},
"data_count" : {
"value" : "299",
"unit" : "#"
}
}
],
"graph_option" : [{
"name" : "perfwarning",
"value" : "-",
"unit" : "seconds"
}, {
"name" : "perfcritical",
"value" : "-",
"unit" : "seconds"
}, {
"name" : "availwarning",
"value" : "-",
"unit" : "percent"
}, {
"name" : "availcritical",
"value" : "-",
"unit" : "percent"
}, {
"name" : "bucketsize",
"value" : "86400",
"unit" : "seconds"
}, {
"name" : "rows",
"value" : "1",
"unit" : "#"
}, {
"name" : "pagecomponent",
"value" : "Total Time",
"unit" : "seconds"
}, {
"name" : "avg_perf",
"value" : "2.244",
"unit" : "seconds"
}, {
"name" : "avg_avail",
"value" : "99.67",
"unit" : "percent"
}, {
"name" : "total_datapoint_count",
"value" : "300",
"unit" : "#"
}, {}
]
}, {
"id" : "9997666",
"alias" : "Measurement (TxP)[IE]-Women - Total Time (seconds)",
"bucket_data" : [{
"name" : "2013-MAR-18 12:00 AM",
"id" : 1,
"perf_data" : {
"value" : "0.979",
"unit" : "seconds"
},
"avail_data" : {
"value" : "100.00",
"unit" : "percent"
},
"data_count" : {
"value" : "299",
"unit" : "#"
}
}
],
"graph_option" : [{
"name" : "perfwarning",
"value" : "-",
"unit" : "seconds"
}, {
"name" : "perfcritical",
"value" : "-",
"unit" : "seconds"
}, {
"name" : "availwarning",
"value" : "-",
"unit" : "percent"
}, {
"name" : "availcritical",
"value" : "-",
"unit" : "percent"
}, {
"name" : "bucketsize",
"value" : "86400",
"unit" : "seconds"
}, {
"name" : "rows",
"value" : "1",
"unit" : "#"
}, {
"name" : "pagecomponent",
"value" : "Total Time",
"unit" : "seconds"
}, {
"name" : "avg_perf",
"value" : "0.979",
"unit" : "seconds"
}, {
"name" : "avg_avail",
"value" : "100.00",
"unit" : "percent"
}, {
"name" : "total_datapoint_count",
"value" : "299",
"unit" : "#"
}, {}
]
}
],
"link" : {
"type" : "application/json",
"href" : "http://api.website.tld?format=json",
"rel" : "slotmetadata"
}
}
Class for Json.NET:
using System;
using System.Collections.Generic;
namespace CAKR.Graph
{
/// <summary>
/// Description of KN_Graph.
/// </summary>
public class GraphProperty
{
public string name { get; set; }
public string value { get; set; }
}
public class PerfData
{
public string value { get; set; }
public string unit { get; set; }
}
public class AvailData
{
public string value { get; set; }
public string unit { get; set; }
}
public class DataCount
{
public string value { get; set; }
public string unit { get; set; }
}
public class BucketData
{
public string name { get; set; }
public int id { get; set; }
public PerfData perf_data { get; set; }
public AvailData avail_data { get; set; }
public DataCount data_count { get; set; }
}
public class GraphOption
{
public string name { get; set; }
public string value { get; set; }
public string unit { get; set; }
}
public class Measurement
{
public string id { get; set; }
public string alias { get; set; }
public List<BucketData> bucket_data { get; set; }
public List<GraphOption> graph_option { get; set; }
}
public class Link
{
public string type { get; set; }
public string href { get; set; }
public string rel { get; set; }
}
public class RootObject
{
public List<GraphProperty> graph_property { get; set; }
public List<Measurement> measurement { get; set; }
public Link link { get; set; }
}
}
My code:
var myObject = JsonConvert.DeserializeObject<CAKR.Graph.Measurement>(MyJsonString);
I'm not sure why I don't get an object containing the data of the "Measurment" child-array.
If I insert named values, it works...
So I was struggling for quite some time to get this working. However in the end the solution is not so difficult. Hopefully with my response I will help some people.
The solution in my case was
Install JSON.net into your project by using nu.get
Make your JSON object including array's in array's, etc. Be sure that the format of the object is correct! Example...
{"ProductDetail":[
{
"ProjectImg" : "http://placehold.it/400x300",
"Category" : "Cars",
"ProjectTitle" : "Cars of the future",
"ProjectDesc" : "Test project",
"GenSpecList" : ["Specs1", "Specs2", "Specs3", "Specs4"],
"OptionList" : [{ "OptionNr" : "1",
"Options" : ["Opt1", "Opt2", "Opt3"]
},
{ "OptionNr" : "2",
"Options" : ["Opt1", "Opt2", "Opt3"]
},
{ "OptionNr" : "3",
"Options" : ["Opt1", "Opt2", "Opt3"]
},
{ "OptionNr" : "4",
"Options" : ["Opt1", "Opt2", "Opt3"]
},
{ "OptionNr" : "5",
"Options" : ["Opt1", "Opt2", "Opt3"]
},
{ "OptionNr" : "6",
"Options" : ["Opt1", "Opt2", "Opt3"]
}
],
"Articles" : [{ "tileImg" : "'Images/Project/1.jpg'",
"tileTit" : "Title1",
"tileArt" : "Article text here..."
},
{
"tileImg" : "'Images/Project/2.jpg'",
"tileTit" : "Title2",
"tileArt" : "Article text here..."
},
{
"tileImg" : "'Images/Project/3.jpg'",
"tileTit" : "Title3",
"tileArt" : "Article text here..."
},
{
"tileImg" : "'Images/Project/4.jpg'",
"tileTit" : "Title4",
"tileArt" : "Article text here..."
}
]
}
]
}
Go to json2csharp.com and copy your JSON object into the input box and click on the generate button. Copy the csharp model (this was actually the key to solve my struggle!) generated into your ViewModel.
In my case the primary class of all generated classes by json2csharp.com was the RootObject and looked like below
public class Article
{
public string tileImg { get; set; }
public string tileTit { get; set; }
public string tileArt { get; set; }
}
public class OptionList
{
public string OptionNr { get; set; }
public List<string> Options { get; set; }
}
public class ProductDetail
{
public string ProjectImg { get; set; }
public string Category { get; set; }
public string ProjectTitle { get; set; }
public string ProjectDesc { get; set; }
public List<string> GenSpecList { get; set; }
public List<OptionList> OptionList { get; set; }
public List<Article> Articles { get; set; }
}
public class RootObject
{
public List<ProductDetail> ProductDetail { get; set; }
}
Then use the following code in the controller (just copied the complete file here)
using Project.Details; //<-- this is my ViewModel namespace name
using Newtonsoft.Json;
using System.IO;
using System.Threading.Tasks;
namespace WebApplication.Controllers
{
public class JSONController : Controller
{
//
// GET: /JSON/
public async Task<ActionResult> Index()
{
StreamReader file = new StreamReader("C:\\Users\\YourName\\etc\\File.json");
String json = await file.ReadToEndAsync();
var Project = JsonConvert.DeserializeObject<RootObject>(json);
return View();
}
}
}
Now everything should work fine, array's in array's etc.
Hope that you found my solution helpful, note I'm not a die hard programmer so if I miss things on efficency I hope to recieve some tips from you to improve this code...
Best regards,
Raymond
You are almost there. Just use
var myObject = JsonConvert.DeserializeObject<CAKR.Graph.RootObject>(MyJsonString);
instead of
var myObject = JsonConvert.DeserializeObject<CAKR.Graph.Measurement>(MyJsonString);
First of all, you do not really need to name all the properties of your Measurement class exactly as they are presented in MyJsonString. You can use JsonProperty attribute and decorate your class properties.
Another thing is if you want to deserialize part of your MyJsonString and extract only array of Measurement, you should provide correct T type for Deserialize method (in your case it's IEnumerable<Measurement>.
The following code should help:
dynamic context = JObject.Parse(MyJsonString);
var myObject = JsonConvert.DeserializeObject<IEnumerable<Measurement>>(context.measurement.ToString());
I use a very simple method to Deserialize Json Arrays. Instead of using a ton of public classes with numerous public variables. I just use a Dynamic object and pass json as an object to JSONConvert.DeserializeObject.
This is how it would work. Say I have the following JSON:
string json = { 'Name': 'John Doe',
'Address': { 'City': 'Atlanta', 'State': 'GA' },
'Age': 30}
I can pass string json to the JSONConvert.DeserializeObject.
dynamic outputArray = JsonConvert.DeserializeObject(json);
Then using the dynamic item that was just created I can collect Json data like so.
string getName = outputArray.Name //This will return "John Doe"
If you have an array inside your Json you can use
string getCity = outputArray.Address.City; //This will return "Atlanta".
It's very easy to change where you pull data from without having a cluster of public variables... You can still save the values to public variables if you want.
The following is how I use the complete method:
using (var client = new WebClient())
{
string json = client.DownloadString(url);
string output = json.ToString();
dynamic outputArray = JsonConvert.DeserializeObject(output);
string _age = outputArray.age;
string appID = outputArray.data.app_id;
Debug.Write(outputArray.Something); //Just match value of json
}
Related
I have a json file as follows:
{
"container" : {
"cans1" :
[
{
"name" : "sub",
"ids" :
[
"123"
]
},
{
"name" : "Fav",
"ids" :
[
"1245","234"
]
},
{
"name" : "test",
"ids" :
[
"DOC12","DOC1234"
]
}
],
"ids" :
[
"1211","11123122"
],
"cans2" :
[
{
"name" : "sub1",
"ids" :
[
"123"
]
}
],
"ids" :
[
"121","11123"
]
}
I want to fetch name values sub,fav,test and ids for each cans in this json file using c#
Install nuget Newtonsoft.Json. Create next hierarchy:
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public class MyClass
{
[JsonProperty("container")]
public Container Container { get; set; }
}
public class Container
{
[JsonProperty("cans1")]
public Cans[] Cans1 { get; set; }
[JsonProperty("ids")]
[JsonConverter(typeof(DecodeArrayConverter))]
public long[] Ids { get; set; }
[JsonProperty("cans2")]
public Cans[] Cans2 { get; set; }
}
public class Cans
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("ids")]
public string[] Ids { get; set; }
}
And then
JsonConvert.DeserializeObject<MyClass>(yourJsonString);
UPD
Based on comment, try this:
var des = JsonConvert.DeserializeObject<MyClass>(t);
foreach(var arr in des.Container.Where(r => r.Key.StartsWith("cans")))
{
Console.WriteLine($"{arr.Key}");
foreach(var elem in arr.Value)
{
Console.WriteLine($" {elem.Value<string>("name")}");
}
}
public class MyClass
{
[JsonProperty("container")]
public Dictionary<string, JArray> Container { get; set; }
}
I am trying to parse the AWS EC2 Reading an Offer File JSON file and I have a problem reading it. As you can see in the JSON file, there is a list of products and the key value of the JSON file is different each time and I cannot read it.
Any ideas how to read the file?
"Reserved" : {
"DQ578CGN99KG6ECF" : {
"DQ578CGN99KG6ECF.HU7G6KETJZ" : {
"offerTermCode" : "HU7G6KETJZ",
"sku" : "DQ578CGN99KG6ECF",
"effectiveDate" : "2017-02-28T23:59:59Z",
"priceDimensions" : {
"DQ578CGN99KG6ECF.HU7G6KETJZ.2TG2D8R56U" : {
"rateCode" : "DQ578CGN99KG6ECF.HU7G6KETJZ.2TG2D8R56U",
"description" : "Upfront Fee",
"unit" : "Quantity",
"pricePerUnit" : {
"USD" : "11213"
},
"appliesTo" : [ ]
},
"DQ578CGN99KG6ECF.HU7G6KETJZ.6YS6EN2CT7" : {
"rateCode" : "DQ578CGN99KG6ECF.HU7G6KETJZ.6YS6EN2CT7",
"description" : "Windows (Amazon VPC), hs1.8xlarge instance-hours used this month",
"beginRange" : "0",
"endRange" : "Inf",
"unit" : "Hrs",
"pricePerUnit" : {
"USD" : "1.2510000000"
},
"appliesTo" : [ ]
}
},
"termAttributes" : {
"LeaseContractLength" : "1yr",
"OfferingClass" : "standard",
"PurchaseOption" : "Partial Upfront"
}
},
"DQ578CGN99KG6ECF.38NPMPTW36" : {
"offerTermCode" : "38NPMPTW36",
"sku" : "DQ578CGN99KG6ECF",
"effectiveDate" : "2015-04-30T23:59:59Z",
"priceDimensions" : {
"DQ578CGN99KG6ECF.38NPMPTW36.2TG2D8R56U" : {
"rateCode" : "DQ578CGN99KG6ECF.38NPMPTW36.2TG2D8R56U",
"description" : "Upfront Fee",
"unit" : "Quantity",
"pricePerUnit" : {
"USD" : "16924"
},
"appliesTo" : [ ]
},
"DQ578CGN99KG6ECF.38NPMPTW36.6YS6EN2CT7" : {
"rateCode" : "DQ578CGN99KG6ECF.38NPMPTW36.6YS6EN2CT7",
"description" : "Windows (Amazon VPC), hs1.8xlarge instance-hours used this month",
"beginRange" : "0",
"endRange" : "Inf",
"unit" : "Hrs",
"pricePerUnit" : {
"USD" : "1.0910000000"
},
"appliesTo" : [ ]
}
},
"termAttributes" : {
"LeaseContractLength" : "3yr",
"OfferingClass" : "standard",
"PurchaseOption" : "Partial Upfront"
}
},
"DQ578CGN99KG6ECF.NQ3QZPMQV9" : {
"offerTermCode" : "NQ3QZPMQV9",
"sku" : "DQ578CGN99KG6ECF",
"effectiveDate" : "2015-04-30T23:59:59Z",
"priceDimensions" : {
"DQ578CGN99KG6ECF.NQ3QZPMQV9.6YS6EN2CT7" : {
"rateCode" : "DQ578CGN99KG6ECF.NQ3QZPMQV9.6YS6EN2CT7",
"description" : "USD 0.0 per Windows (Amazon VPC), hs1.8xlarge instance-hour (or partial hour)",
"beginRange" : "0",
"endRange" : "Inf",
"unit" : "Hrs",
"pricePerUnit" : {
"USD" : "0.0000000000"
},
"appliesTo" : [ ]
},
"DQ578CGN99KG6ECF.NQ3QZPMQV9.2TG2D8R56U" : {
"rateCode" : "DQ578CGN99KG6ECF.NQ3QZPMQV9.2TG2D8R56U",
"description" : "Upfront Fee",
"unit" : "Quantity",
"pricePerUnit" : {
"USD" : "42860"
},
"appliesTo" : [ ]
}
},
"termAttributes" : {
"LeaseContractLength" : "3yr",
"OfferingClass" : "standard",
"PurchaseOption" : "All Upfront"
}
},
You may use Dictionary<string, ...> whenever encounter variable keys with well-structured values:
var obj = JsonConvert.DeserializeObject<RootObject>(json);
foreach (var offer in obj.Reserved.Values.SelectMany(v => v.Values))
{
Console.WriteLine(offer.effectiveDate);
foreach (var priceDim in offer.priceDimensions.Values)
Console.WriteLine("\t" + priceDim.description);
}
// .....................
public class RootObject
{
public Dictionary<string, Dictionary<string, Offer>> Reserved { get; set; }
}
public class Offer
{
public string offerTermCode { get; set; }
public string sku { get; set; }
public DateTime effectiveDate { get; set; }
public Dictionary<string, PriceDimension> priceDimensions { get; set; }
public TermAttributes termAttributes { get; set; }
}
public class PriceDimension
{
public string rateCode { get; set; }
public string description { get; set; }
public string beginRange { get; set; }
public string endRange { get; set; }
public string unit { get; set; }
public Dictionary<string, string> pricePerUnit { get; set; }
public object[] appliesTo { get; set; }
}
public class TermAttributes
{
public string LeaseContractLength { get; set; }
public string OfferingClass { get; set; }
public string PurchaseOption { get; set; }
}
Demo: https://dotnetfiddle.net/Nj7lz2
N.B. I'm assuming you process the JSON in C# using JSON.Net.
This seems to be much like a duplicate of Deserializing dates with dd/mm/yyyy format using Json.Net but the proposed solution doesn't seem to work for me.
I have a test case
void Main()
{
if (File.Exists("config.json"))
{
string json = File.ReadAllText("config.json");
var dateTimeConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter { DateTimeFormat = "dd/MM/yyyy" };
PositionForwardingConfiguration config = Newtonsoft.Json.JsonConvert.DeserializeObject<PositionForwardingConfiguration>(json, dateTimeConverter);
foreach (var client in config.ClientConfiguration.clients)
{
Debug.WriteLine(string.Format("Date: {0}", client.MiniumDate));
}
json = Newtonsoft.Json.JsonConvert.SerializeObject(config, dateTimeConverter);
Debug.WriteLine(json);
}
}
public class PositionForwardingConfiguration
{
public ClientConfiguration ClientConfiguration { get; set; }
}
public class ClientConfiguration
{
public ClientInfo[] clients { get; set; }
}
public class ClientInfo
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime MiniumDate { get; set; }
public string Token { get; set; }
public Uri Endpoint { get; set; }
}
that produces output like
Date: 1/1/0001 12:00:00 AM
Date: 1/1/0001 12:00:00 AM
Date: 1/1/0001 12:00:00 AM
{"ClientConfiguration":{"clients":[{"Id":1,"Name":"1","MiniumDate":"01/01/0001","Token":"Token 1","Endpoint":"http://1"},{"Id":2,"Name":"2","MiniumDate":"01/01/0001","Token":"Token 2","Endpoint":"http://2"},{"Id":3,"Name":"3","MiniumDate":"01/01/0001","Token":"Token 3","Endpoint":"http://3"}]}}
Particular note the date is not deserializing or serializing using the supplied converter. Has something changed with Newtonsoft.JSON to make this not work? My input looks like
{
"ClientConfiguration": {
"clients": [
{
"Id" : 1,
"Name" : "1",
"MinimumDate" : "01/01/2017",
"Token" : "Token 1",
"Endpoint" : "http://1"
},
{
"Id" : 2,
"Name" : "2",
"MinimumDate" : "02/01/2017",
"Token" : "Token 2",
"Endpoint" : "http://2"
},
{
"Id" : 3,
"Name" : "3",
"MinimumDate" : "03/01/2017",
"Token" : "Token 3",
"Endpoint" : "http://3"
}
]
}
}
Ideas?
I've registered a class to pull addresses out of the a restaurants collection:
BsonClassMap.RegisterClassMap<RestaurantAddress>(map =>
{
map.MapMember(c => c.Id).SetElementName(("_id"));
map.MapMember(c => c.Building).SetElementName("address.building");
map.MapMember(c => c.Street).SetElementName("address.street");
map.MapMember(c => c.ZipCode).SetElementName("address.zipcode");
});
The Mongo document looks like:
{
"_id" : ObjectId("56bb82621ff72e0d9ba267cb"),
"address" : {
"building" : "6409",
"coord" : [
-74.005289,
40.628886
],
"street" : "11 Avenue",
"zipcode" : "11219"
},
"borough" : "Brooklyn",
"cuisine" : "American ",
"grades" : [
{
"date" : ISODate("2014-07-18T00:00:00.000Z"),
"grade" : "A",
"score" : 12
},
{
"date" : ISODate("2013-07-30T00:00:00.000Z"),
"grade" : "A",
"score" : 12
}
],
"name" : "Regina Caterers",
"restaurant_id" : "40356649"
}
When I get the document, the nested elements are all null though:
[Test]
public void DeserializeToAddress()
{
var collection = _database.GetCollection<RestaurantAddress>("grades");
var address = collection.Find(a => a.Id == new ObjectId("56bb82621ff72e0d9ba267cb")).Limit(1).Single();
Assert.That(address.Id, Is.Not.Null);
Assert.That(address.Building, Is.Not.Null);
Assert.That(address.Street, Is.Not.Null);
}
How should I be referencing nested elements?
The class to serialize into is:
internal class RestaurantAddress
{
public ObjectId Id { get; set; }
public string Building { get; set; }
public string Street { get; set; }
public string ZipCode { get; set; }
public Point CoordsPoint { get; set; }
}
Currenlty, I don't have anything for hyrating the CoordsPoint object. That's for a later excercise.
We currently don't support pulling nested elements out into a parent document. This would be a feature request. You can file that at jira.mongodb.org under the CSHARP project. Alternatively, you can write a custom serializer to handle this particular scenario if you'd like.
Craig
I have a class in my ASP.NET MVC project which calls the Google MAPS Autocomplete API
public ActionResult Autocomplete(string term)
{
var url = String.Format(" https://maps.googleapis.com/maps/api/place/autocomplete/json?input=" + term + "&types=address&location=53.4333,-7.9500&radius=250&key=MYKEY");
var jsonautocomplete = new System.Net.WebClient().DownloadString(url);
JavaScriptSerializer jss = new JavaScriptSerializer();
Rootobject autocomplete = JsonConvert.DeserializeObject<Rootobject>(jsonautocomplete);
string suggestions = (autocomplete.predictions[5].description[0].value);
return Json(suggestions, JsonRequestBehavior.AllowGet);
}
This is to create a call to the Google MAPS API which dynamically creates a URL to the API based the value which is in turn passed into the function as term).
I also have supporting classes in the same controller to deserialise (not sure this is the correct term) the returned JSON.
public class Rootobject
{
public Prediction[] predictions { get; set; }
public string status { get; set; }
}
public class Prediction
{
public string description { get; set; }
public string id { get; set; }
public Matched_Substrings[] matched_substrings { get; set; }
public string place_id { get; set; }
public string reference { get; set; }
public Term[] terms { get; set; }
public string[] types { get; set; }
}
public class Matched_Substrings
{
public int length { get; set; }
public int offset { get; set; }
}
public class Term
{
public int offset { get; set; }
public string value { get; set; }
}
I can see that this is correctly returning JSON formatted data which contains the address suggestions but I am having issues with deserialising it correctly
{
"predictions" : [
{
"description" : "92 Howth Road, Clontarf, Ireland",
"id" : "c949817fec719bf89a8f03aa5e4e24bb26c3c2c2",
"matched_substrings" : [
{
"length" : 8,
"offset" : 0
}
],
"place_id" : "EiA5MiBIb3d0aCBSb2FkLCBDbG9udGFyZiwgSXJlbGFuZA",
"reference" : "ClROAAAAPPyMTROIaAQ52qM2ixB_TY7ZHczbKDWLzIRQHXP0bfo3-qRjDKyuNgg9xbzUweWRkEleIbRh9P-Pp9dsyrgPXI9cHNlzi6Em-mQzLiFyh0ESEA21MGZZ9E_kgFc9idXn73gaFIuJF8FsllcDIoi4XFc7iLsp814l",
"terms" : [
{
"offset" : 0,
"value" : "92 Howth Road"
},
{
"offset" : 15,
"value" : "Clontarf"
},
{
"offset" : 25,
"value" : "Ireland"
}
],
"types" : [ "route", "geocode" ]
},
{
"description" : "92 Howth Road, Dublin, Ireland",
"id" : "58992f3ede4055683f2d67510aae48913e7b196c",
"matched_substrings" : [
{
"length" : 8,
"offset" : 0
}
],
"place_id" : "Eh45MiBIb3d0aCBSb2FkLCBEdWJsaW4sIElyZWxhbmQ",
"reference" : "ClRMAAAA5neJBhWV_AstgsVtw-pahbLn406FbDBgehGuQbj5totChvsPNnPXkVwmqYnzZ38FOliK-egwTXaa195I92MYrkc6cOHHhRzUnZTTrzTx3CUSEJq0FGcZDiudfzUtWvRDHC4aFOqddOIfGFfrSu3kcCCpOIiCSm-m",
"terms" : [
{
"offset" : 0,
"value" : "92 Howth Road"
},
{
"offset" : 15,
"value" : "Dublin"
},
{
"offset" : 23,
"value" : "Ireland"
}
],
"types" : [ "route", "geocode" ]
},
{
"description" : "92 Howth View Park, Dublin, Ireland",
"id" : "6947a633c77f6fb087893ce39a7a22c862d3d9cb",
"matched_substrings" : [
{
"length" : 8,
"offset" : 0
}
],
"place_id" : "EiM5MiBIb3d0aCBWaWV3IFBhcmssIER1YmxpbiwgSXJlbGFuZA",
"reference" : "CmRRAAAAcJV1nTt6EfZ2hhapaCETKtHE08S7WSqH6kwD57jiUtrRrVMvktjzL-Bftb5RHU1g4Sbe4bOPZUUzn5qMTI-GJWNNrpEz5iNNPRihRZMq5Q-TLFSCGhETXog3vhRWguIhEhAqvFrZnOTos2fsljbScA0EGhTEcsUy1-uXeRJoClm7jO2QoNj3ow",
"terms" : [
{
"offset" : 0,
"value" : "92 Howth View Park"
},
{
"offset" : 20,
"value" : "Dublin"
},
{
"offset" : 28,
"value" : "Ireland"
}
],
"types" : [ "route", "geocode" ]
},
{
"description" : "92 Howth Track, Ashtown, Dublin, Ireland",
"id" : "abb6fb12e2455de2a931729152b626c0f213ac82",
"matched_substrings" : [
{
"length" : 8,
"offset" : 0
}
],
"place_id" : "Eig5MiBIb3d0aCBUcmFjaywgQXNodG93biwgRHVibGluLCBJcmVsYW5k",
"reference" : "CmRWAAAADGi1rI3efQ6CqZ9zu9qc9gstGf7kZiN973ZyqkeZNnZnyilV2A-dvo7Y8tPad8DNR_ovNeuXGmZDNhPZTjbv0G4D2Jrmdk5qtvBRQDg0EUMtcUNuOzwp_8coqoFI4zLGEhBSurI0GFQlC5X25rJ4MWH2GhRGJN63O_Qx_uVz9tajiILekzPEug",
"terms" : [
{
"offset" : 0,
"value" : "92 Howth Track"
},
{
"offset" : 16,
"value" : "Ashtown"
},
{
"offset" : 25,
"value" : "Dublin"
},
{
"offset" : 33,
"value" : "Ireland"
}
],
"types" : [ "route", "geocode" ]
},
{
"description" : "92 Howth Terrace, Dublin, Ireland",
"id" : "bf78cde30e173f6e2fbc62fac3bd4a1c31829303",
"matched_substrings" : [
{
"length" : 8,
"offset" : 0
}
],
"place_id" : "EiE5MiBIb3d0aCBUZXJyYWNlLCBEdWJsaW4sIElyZWxhbmQ",
"reference" : "ClRPAAAA_gOsPjZCyAcES4P3ohJQTtJp4bGzP-gwZHioxoBbSbQjqRG2Z0-v89vBsJ6pSVBW_GVMvIFU7tIS_4TaDp2qr6Ah0XwmhY6wBaeO3Aq-Jt4SEJfAyiwx6XmaJGQUI6iHbTYaFBnIlHERvz37KRM7bp211RgWjC7J",
"terms" : [
{
"offset" : 0,
"value" : "92 Howth Terrace"
},
{
"offset" : 18,
"value" : "Dublin"
},
{
"offset" : 26,
"value" : "Ireland"
}
],
"types" : [ "route", "geocode" ]
}
],
"status" : "OK"
}
HOWEVER
The suggestions string is null (it should contain the returned suggestions from parsing the JSON from Google MAPS and taking the description attributes- the API returns the best 5 matches) and Visual Studio throws an out of range exception.
I am fairly sure the error lies in this line of code which is not deserialising the JSON correctly.
string suggestions = (autocomplete.predictions[5].description[0].value);
I am trying to pass these values through into a JQUERY function on the Index view of the Entity that this controller relates to as follows:
<form method="get" action="#Url.Action("Index")"
data-otf-ajax="true" data-otf-target="#restaurantList">
<input type="search" name="searchTerm" data-otf-autocomplete="#Url.Action("Autocomplete")" />
<input type="submit" value="Search By Name" />
</form>
The JSON being returned needs to contain values that in something like the following format
[0] {label ="92 Howth Road, Clontarf, Ireland"
[1] {label ="92 Howth Road, Dublin, Ireland"}
[2] {label ="92 Howth View Park, Dublin, Ireland"}
Apologies if the JSON format above is not exact, just trying to show which of the longer list of the JSON attributes coming back from the Google MAPS API I'm interested in autofilling to the form.
As you'll see above these are the "description" attributes in the JSON originally returned
I would be very grateful for advice on how to correctly update this line to grab the right values:
string suggestions = (autocomplete.predictions[5].description[0].value);
Thank you
try using lists instead of arrays in your class http://json2csharp.com/
PS, VS paste special as classes does the same thing.(deserialize is correct)
public class MatchedSubstring
{
public int length { get; set; }
public int offset { get; set; }
}
public class Term
{
public int offset { get; set; }
public string value { get; set; }
}
public class Prediction
{
public string description { get; set; }
public string id { get; set; }
public List<MatchedSubstring> matched_substrings { get; set; }
public string place_id { get; set; }
public string reference { get; set; }
public List<Term> terms { get; set; }
public List<string> types { get; set; }
}
public class RootObject
{
public List<Prediction> predictions { get; set; }
public string status { get; set; }
}
Using saj's suggestion above to use a list object and not an array, the following updated method works.
public ActionResult Autocomplete(string term)
{
var url = String.Format(" https://maps.googleapis.com/maps/api/place/autocomplete/json?input=" + term + "&types=address&location=53.4333,-7.9500&radius=250&key=MYKEY");
var jsonautocomplete = new System.Net.WebClient().DownloadString(url);
JavaScriptSerializer jss = new JavaScriptSerializer();
Rootobject autocomplete = JsonConvert.DeserializeObject<Rootobject>(jsonautocomplete);
var suggestions = autocomplete.predictions;
var model = suggestions.Select(x => new
{
label = x.description
});
return Json(model, JsonRequestBehavior.AllowGet);
}