I'm having a ton of trouble trying to access the nested json data (pasted at the bottom). I'm able write:
var dataResults = jsonResult["data"] as NSDictionary
In order to create a dictionary containing the data within "data", however, Xcode will not allow me to call on anything within "data" such as the information within "current_condition". I've tried to make current_condition it's own dictionary like so:
var results = dataResults["current_condition"] as NSDictionary
But it would seem that this is turning up as nil
I have also attempted accessing using the standard method for calling nested loops:
var dataResults = jsonResult["data"]["current_condition"] as NSDictionary
But this results in a compiler error.
Any help? Much appreciated!
Json data:
{
data = {
"current_condition" = (
{
cloudcover = 0;
humidity = 68;
"observation_time" = "01:39 AM";
precipMM = "0.0";
pressure = 1017;
"temp_C" = 20;
"temp_F" = 68;
visibility = 10;
weatherCode = 143;
weatherDesc = (
{
value = Mist;
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0006_mist.png";
}
);
winddir16Point = NE;
winddirDegree = 50;
windspeedKmph = 7;
windspeedMiles = 4;
}
);
request = (
{
query = "London, United Kingdom";
type = City;
}
);
weather = (
{
date = "2014-07-25";
precipMM = "1.5";
tempMaxC = 27;
tempMaxF = 81;
tempMinC = 14;
tempMinF = 57;
weatherCode = 353;
weatherDesc = (
{
value = "Light rain shower";
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0009_light_rain_showers.png";
}
);
winddir16Point = NE;
winddirDegree = 54;
winddirection = NE;
windspeedKmph = 15;
windspeedMiles = 10;
},
{
date = "2014-07-26";
precipMM = "5.8";
tempMaxC = 28;
tempMaxF = 83;
tempMinC = 16;
tempMinF = 61;
weatherCode = 176;
weatherDesc = (
{
value = "Patchy rain nearby";
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0009_light_rain_showers.png";
}
);
winddir16Point = NNE;
winddirDegree = 12;
winddirection = NNE;
windspeedKmph = 11;
windspeedMiles = 7;
},
{
date = "2014-07-27";
precipMM = "0.2";
tempMaxC = 26;
tempMaxF = 80;
tempMinC = 13;
tempMinF = 55;
weatherCode = 116;
weatherDesc = (
{
value = "Partly Cloudy";
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png";
}
);
winddir16Point = NW;
winddirDegree = 321;
winddirection = NW;
windspeedKmph = 14;
windspeedMiles = 9;
},
{
date = "2014-07-28";
precipMM = "1.9";
tempMaxC = 26;
tempMaxF = 78;
tempMinC = 12;
tempMinF = 54;
weatherCode = 116;
weatherDesc = (
{
value = "Partly Cloudy";
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png";
}
);
winddir16Point = N;
winddirDegree = 351;
winddirection = N;
windspeedKmph = 13;
windspeedMiles = 8;
},
{
date = "2014-07-29";
precipMM = "0.0";
tempMaxC = 28;
tempMaxF = 82;
tempMinC = 16;
tempMinF = 60;
weatherCode = 113;
weatherDesc = (
{
value = Sunny;
}
);
weatherIconUrl = (
{
value = "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0001_sunny.png";
}
);
winddir16Point = NNW;
winddirDegree = 329;
winddirection = NNW;
windspeedKmph = 13;
windspeedMiles = 8;
}
);
};
}
Oddly enough, I have a sample weather app that I converted to Swift. I get my data elsewhere, but I found this library to be a great way to deal with JSON in Swift: https://github.com/dankogai/swift-json/. Much cleaner and easier.
It's because the subscript in Dictionary returns an optional:
subscript (key: KeyType) -> ValueType?
Meaning you have to unwrap the optional before you can downcast:
let dataResults = jsonResult["data"]! as NSDictionary
let results = dataResults["current_condition"]! as NSDictionary
As of Beta 3 you can access the value directly without downcasting, like this:
let dataResults = jsonResult["data"]!
let results = dataResults["current_condition"]
However I would suggest you wrap it around an if-let to make sure you don't unwrap nil values.
Related
I have a json response as follows
{
"payment_methods" = (
{
code = checkmo;
title = "Check / Money order";
},
{
code = "paypal_express";
title = "PayPal Express Checkout";
},
{
code = banktransfer;
title = "Bank Transfer Payment";
}
);
totals = {
"base_currency_code" = USD;
"base_discount_amount" = "-258.38";
"base_grand_total" = "2725.37";
"base_shipping_amount" = 400;
"base_shipping_discount_amount" = 0;
"base_shipping_incl_tax" = 400;
"base_shipping_tax_amount" = 0;
"base_subtotal" = "2583.75";
"base_subtotal_with_discount" = "2325.37";
"base_tax_amount" = 0;
"coupon_code" = ADAMAS10;
"discount_amount" = "-258.38";
"grand_total" = "2725.37";
items = (
{
"base_discount_amount" = "134.2";
"base_price" = 1342;
"base_price_incl_tax" = 1342;
"base_row_total" = 1342;
"base_row_total_incl_tax" = 1342;
"base_tax_amount" = 0;
"discount_amount" = "134.2";
"discount_percent" = 10;
"item_id" = 3292;
name = BWBCA14KWGVC015;
options = "[{\"value\":\"18K White Gold\",\"label\":\"Metal\"},{\"value\":\"2\",\"label\":\"size\"}]";
price = 1342;
"price_incl_tax" = 1342;
qty = 1;
"row_total" = 1342;
"row_total_incl_tax" = 1342;
"row_total_with_discount" = 0;
"tax_amount" = 0;
"tax_percent" = 0;
"weee_tax_applied" = "[]";
"weee_tax_applied_amount" = 0;
},
{
"base_discount_amount" = "124.18";
"base_price" = "1241.75";
"base_price_incl_tax" = "1241.75";
"base_row_total" = "1241.75";
"base_row_total_incl_tax" = "1241.75";
"base_tax_amount" = 0;
"discount_amount" = "124.18";
"discount_percent" = 10;
"item_id" = 3342;
name = BWBCA14KWGCV008;
options = "[{\"value\":\"18K White Gold\",\"label\":\"Metal Type\"},{\"value\":\"1.75\",\"label\":\"Ring Size\"}]";
price = "1241.75";
"price_incl_tax" = "1241.75";
qty = 1;
"row_total" = "1241.75";
"row_total_incl_tax" = "1241.75";
"row_total_with_discount" = 0;
"tax_amount" = 0;
"tax_percent" = 0;
"weee_tax_applied" = "[]";
"weee_tax_applied_amount" = 0;
}
);
"items_qty" = 2;
"quote_currency_code" = USD;
"shipping_amount" = 400;
"shipping_discount_amount" = 0;
"shipping_incl_tax" = 400;
"shipping_tax_amount" = 0;
subtotal = "2583.75";
"subtotal_incl_tax" = "2583.75";
"subtotal_with_discount" = "2325.37";
"tax_amount" = 0;
"total_segments" = (
{
code = subtotal;
title = Subtotal;
value = "2583.75";
},
{
code = discount;
title = "Discount (ADAMAS10)";
value = "-258.38";
},
{
code = shipping;
title = "Shipping & Handling (Flat Shipping Charge - Flat Shipping Charge)";
value = 400;
},
{
area = taxes;
code = tax;
"extension_attributes" = {
"tax_grandtotal_details" = (
);
};
title = Tax;
value = 0;
},
{
area = footer;
code = "grand_total";
title = "Grand Total";
value = "2725.37";
}
);
"weee_tax_applied_amount" = "<null>";
};
}
I need to fetch values from total segments.The code is shipping and value is Shipping & Handling (Flat Shipping Charge - Flat Shipping Charge.
I tried to parse the json using the below code
if let res = json as? [String:Any]
{
if let dict = res as? [String:Any]
{
if let total = dict as? [[String:Any]]
{
}
}
}
I am getting value till dict.But i am getting nil in the total variable.
How to get the total segments value?
you're missing out to mention the inner key path of the dictionary. hope this is what you're trying to do
if let res = json as? [String:Any] {
if let paymentMethods = res["payment_methods"] as? [[String:Any]] {
}
if let totals = res["totals"] as? [String:Any] {
if let items = totals["items"] as? [[String:Any]] {
}
}
}
Use this to get the total_segments and value of all code keys:
var codes = [String]()
if let res = json as? [String:Any] {
if let totals = res["totals"] as? [String:Any] {
if let totalSegments = totals["total_segments"] as? [[String:Any]] {
for segment in totalSegments {
if let code = segment["code"] as? String {
codes.append(code)
}
}
}
}
}
//array
var boxs: Array = new Array
boxs[0] = [b1.x = 307.95 , b1.y = 202]
boxs[1] = [b2.x = 233.95 , b2.y = 202]
boxs[2] = [b3.x = 159.95 , b3.y = 202]
//varable
var oldg:Number = 0
//random number
oldg = Number(Math.floor(Math.random()*boxs.length))
Naive approach:
public function Main()
{
const array:Array = [1,2,3,4,5,6,7];
trace(array);
// 1,2,3,4,5,6,7
swapTwoRandomElements(array);
trace(array);
// 1,2,3,6,5,4,7
}
private function swapTwoRandomElements(input:Array):void
{
const indices:Array = [];
for (var i:int = 0; i < input.length; i++)
{
indices.push(i);
}
const indexFirst:int = indices[int(Math.random() * indices.length)];
indices.splice(indexFirst, 1);
const indexSecond:int = indices[int(Math.random() * indices.length)];
indices.splice(indexSecond, 1);
const tmp:* = input[indexFirst];
input[indexFirst] = input[indexSecond];
input[indexSecond] = tmp;
}
I don't know why this is happening. What I want to do is easy: Create a container and then add a grid of squares in order to build a trivia:
private var square:MovieClip = new MovieClip();
square.width = 308;
square.height = 400;
square.x = 48;
square.y = 223;
square.name = "square";
addChild(square);
private function generarGrilla():void {
var cant = 36;
var col:Number = 5;
var yCounter:Number = -4;
var xCounter:Number = 4;
var sY:Number = 10;
var sX:Number = 10;
for (var j = 1; j < cant; j++) {
var caja:clip = new clip();
caja.name = "opcion" + j;
caja.x = 20 + caja.width * j * 1.2;
caja.y = 20 + caja.height * j * 1.2;;
// caja.x = (sX + caja.width) * xCounter ;
// caja.y = (sY + caja.height) * yCounter;
caja.addEventListener(MouseEvent.CLICK, seleccionarOpcion);
caja.buttonMode = true;
caja.mouseChildren = false;
var contentText = new TextField();
var formato = new TextFormat();
formato.size = 14;
contentText.defaultTextFormat = formato;
contentText.width = 36;
contentText.height = 34;
contentText.x = -10;
contentText.y = -10;
for(var u:uint = 0; u < cant; u++){
contentText.text = "" + u;
}
square.addChild(caja);
caja.addChild(contentText);
}
var barra:score = new score();
barra.x = 80;
barra.y = -200;
barra.puntajeTXT.text = "hola";
addChild(barra);
barra.botonSalir.buttonMode = true;
barra.botonSalir.addEventListener(MouseEvent.CLICK, salirJuego);
}
The square movieclip is placed on the stage without any problem, but I cannot see the grid...
Im trying to make a multidimensional array but I obtain an error ("TypeError: Error #1010: A term is undefined and has no properties.").
var matriz:Array = new Array();
for(var p:Number = 0; p<2;p++ ){
for(var q:Number = 0; q<2;q++ ){
matriz[p][q] = 0;
}
}
what am I doing wrong?
Thanks in advance!
You need to create an array within matriz[p] before you can add an array (or anything else) into it.
You can achieve what you're attempting without errors like this:
var matriz:Array = [];
for(var p:Number = 0; p<2; p++)
{
// Create an array at matriz[p] if undefined.
if(matriz[p] == undefined) matriz[p] = [];
for(var q:Number = 0; q<2; q++)
{
matriz[p][q] = 0;
}
}
Essentially you were trying to do the same as this:
var object:Object = {};
object.nonexistantProperty.value = 10;
What Marty has said is correct, however I prefer removing the if condition and changing the code to the following:
var matriz:Array = [];
for(var p:Number = 0; p<2; p++) {
matriz[p] = [];
for(var q:Number = 0; q<2; q++) {
matriz[p][q] = 0;
}
}
public class cArray
{
private var DIM1CAP:uint=0;
private var DIM2CAP:uint=1;
private var DIM3CAP:uint=2;
private var DIM4CAP:uint=3;
private var DIM5CAP:uint=4;
public function cArray():void
{
// avoid the noid
}
// returns empty array of args.length dimensions
// 1st argument is dim 1 capacity; 2nd is dim 2, etc.
public function getArray ( ... args ):Array
{
var arr = new Array();
if ( paramsNotValid(args) )
{
return null;
}
switch (args.length)
{
case 2:
arr = get2DArray ( args[0], args[1] );
break;
case 3:
arr = get3DArray ( args[0], args[1], args[2] );
break;
case 4:
arr = get4DArray ( args[0], args[1], args[2], args[3] );
break;
case 5:
arr = get5DArray ( args[0], args[1], args[2], args[3], args[4] );
break;
default:
break;
}
return arr;
}
// returns empty 2d array of parameter specified capacity
private function get2DArray ( _1stDimCapacity:uint, _2ndDimCapacity:uint ):Array
{
var arr2d:Array = [];
var arr1d = new Array();
for ( var i:uint=0; i<_1stDimCapacity; i++ )
{
arr1d[_2ndDimCapacity-1] = undefined;
arr2d.push(arr1d);
arr1d = new Array();
}
return arr2d;
}
// returns empty 3d array of parameter specified capacity
private function get3DArray ( dim1Cap:uint,
dim2Cap:uint,
dim3Cap:uint ):Array
{
var arr3d = new Array();
for ( var i:uint=0; i<dim1Cap; i++ )
{
arr3d.push ( get2DArray ( dim2Cap, dim3Cap ) );
}
return arr3d;
}
// returns empty 4d array of parameter specified capacity
private function get4DArray ( dim1Cap:uint,
dim2Cap:uint,
dim3Cap:uint,
dim4Cap:uint):Array
{
var arr4d = new Array();
for ( var i:uint=0; i<dim1Cap; i++ )
{
arr4d.push ( get3DArray ( dim2Cap, dim3Cap, dim4Cap ) );
}
return arr4d;
}
// returns empty 5d array of parameter specified capacity
private function get5DArray ( dim1Cap:uint,
dim2Cap:uint,
dim3Cap:uint,
dim4Cap:uint,
dim5Cap:uint):Array
{
var arr5d = new Array();
for ( var i:uint=0; i<dim1Cap; i++ )
{
arr5d.push ( get4DArray ( dim2Cap, dim3Cap, dim4Cap, dim5Cap ) );
}
return arr5d;
}
//////////////////////////////////////////////////////
private function paramsNotValid ( args:Array ):Boolean
{
if ( args.length<2 || args.length>5 )
{
return true;
}
for ( var i:uint=0; i<args.length; i++ )
{
if ( ! ( args[i]>0 ) )
{
break;
}
}
if ( i < args.length )
{
return true;
}
return false;
}
}
}
public class cMain extends MovieClip
{
var cArr:cArray = new cArray;
public function cMain():void
{
var arr2d:Array;
var arr3d:Array;
var chessBrd_4d:Array;
var arr5d:Array;
// capacity of 10 games; 150 moves/gm; white's mv or black's;
// - piece positions; move in chess notation (index 32 of
// - last dimension); commentary (index 33 of last dimension)
chessBrd_4d = cArr.getArray(10,150,2,34);
// adding data
// - 4th game, 8th move, white's move, positions of pieces
chessBrd_4d[3][7][0][0] = 'd8';
chessBrd_4d[3][7][0][1] = 'b1';
// ...
// - positions of pieces up to last one
// ...
// - last piece pos
chessBrd_4d[3][7][0][31] = 'captured';
// - actual move in chess notation
chessBrd_4d[3][7][0][32] = 'nC4';
// - annotation
chessBrd_4d[3][7][0][33] = 'blocks b pawn, ' +
'opens diag for c1 bishop, ' +
'Justin Beiber is a putz, ' +
'the president is liar'
trace ( 'piece 0 is on square ' + chessBrd_4d[3][7][0][0]);
trace ( 'piece 1 is on square ' + chessBrd_4d[3][7][0][1]);
trace ( ' ... ' )
trace ( 'piece 31 has been ' + chessBrd_4d[3][7][0][31]);
trace ( 'move: ' + chessBrd_4d[3][7][0][32]);
trace ( chessBrd_4d[3][7][0][33]);
/*
trace results:
piece 0 is on square d8
piece 1 is on square b1
...
piece 31 has been captured
move: nC4
blocks b pawn, opens diag for c1 bishop,
Justin Beiber is a putz, the president is liar
*/
/*
trace ( chessBrd_4d.length ); = 10
trace ( chessBrd_4d [ 2 ].length ); = 150
trace ( chessBrd_4d [ 2 ] [ 4 ].length ); = 2
trace ( chessBrd_4d [ 2 ] [ 4 ] [ 1 ].length ); = 34
trace ( chessBrd_4d [ 2 ] [ 4 ] [ 0 ] .length); = 34
*/
}
}
I am able to do this query just fine with the test repository which is In Memory
when I move to the sqlRepository I get this error
Unsupported overload used for query operator 'Intersect'.
I assume it is because sending the query to sql is too complicated for Linq to Sql to do when it is not dealing with the Model.Model.Talent Type. Is there some way around doing a search like this with Intersect?
thanks
public class TalentService : ITalentService
{
ITalentRepository _repository = null;
private IQueryable<Talent> BasicSearch(string searchExpression)
{
IQueryable<Talent> t;
string[] sa = searchExpression.Trim().ToLower().Replace(" ", " ").Split(' ');
t = _repository.GetTalents();
foreach (string s in sa)
{
t = t.Intersect(AddBasicSearch(s), new TalentComparer());
}
return t;
}
private IQueryable<Talent> AddBasicSearch(string s)
{
IQueryable<Talent> t2 = _repository.GetTalents()
.Where(tal => tal.EyeColor.ToString().ToLower().Contains(s)
|| tal.FirstName.ToLower().Contains(s)
|| tal.LastName.ToLower().Contains(s)
|| tal.LanguagesString.ToLower().Contains(s)
);
return t2;
}
}
public class SqlTalentRepository:ITalentRepository
{
public IQueryable<Model.Model.Talent> GetTalents()
{
var tal = from t in _db.Talents
let tLanguage = GetTalentLanguages(t.TalentID)
where t.Active == true
select new Model.Model.Talent
{
Id = t.TalentID,
FirstName = t.FirstName,
LastName = t.LastName,
TalentLanguages = new LazyList<Model.Model.TalentLanguage>(tLanguage),
LanguagesString = t.TalentLanguages.ToLanguageNameString(_LanguageRepository.GetLanguages())
};
return tal ;
}
public IQueryable<Model.Model.TalentLanguage> GetTalentLanguages(int iTalentId)
{
var q = from y in this.talentLanguageList
let Languages = _LanguageRepository.GetLanguages()
where y.TalentId == iTalentId
select new Model.Model.TalentLanguage
{
TalentLanguageId = y.TalentLanguageId,
TalentId = y.TalentId,
LanguageId = y.LanguageId,
Language = Languages.Where(x => x.LanguageId == y.LanguageId).SingleOrDefault()
};
return q.AsQueryable<Model.Model.TalentLanguage>();
}
}
public static class TalentExtensions
{
public static string ToLanguageNameString(this IEnumerable<TalentLanguage> source
, IEnumerable<Model.Model.Language> allLanguages)
{
StringBuilder sb = new StringBuilder();
const string del = ", ";
foreach (TalentLanguage te in source)
{
sb.AppendFormat("{0}{1}", allLanguages
.Where(x => x.LanguageId == te.LanguageID).SingleOrDefault().LanguageName, del);
}
string sReturn = sb.ToString();
if (sReturn.EndsWith(del))
sReturn = sReturn.Substring(0, sReturn.Length - del.Length);
return sReturn;
}
}
public class TestTalentRepository : ITalentRepository
{
IList<Talent> talentList;
public TestTalentRepository(ILanguageRepository _LanguageRepo )
{
this._LanguageRepository = _LanguageRepo;
talentList = new List<Talent>();
talentLanguageList = new List<TalentLanguage>();
for (int i = 0; i < 55; i++)
{
var t = new Talent();
t.Id = i;
t.FirstName = (i % 3 == 0) ? "Ryan" : "Joe";
t.LastName = (i % 2 == 0) ? "Simpson" : "Zimmerman";
AddLanguagesToTestTalent(i, t);
talentList.Add(t);
}
}
private void AddLanguagesToTestTalent(int i, Talent t)
{
IList<Language> Languages = _LanguageRepository.GetLanguages().ToList<Language>();
Random rLanguages = new Random();
int numLanguages = rLanguages.Next(Languages.Count - 1) + 1;
t.TalentLanguages = new LazyList<TalentLanguage>();
for (int j = 0; j < numLanguages; j++)
{
var x = new TalentLanguage();
x.TalentLanguageId = j;
x.TalentId = i;
Random random2 = new Random();
int rand = random2.Next(Languages.Count);
var y = Languages.ElementAtOrDefault(rand);
Languages.RemoveAt(rand);
x.Language = y;
x.LanguageId = y.LanguageId;
t.TalentLanguages.Add(x);
}
}
public IQueryable<Talent> GetTalents()
{
var ts = from t in this.talentList
let tLanguage = GetTalentLanguages(t.Id)
where t.Active == true
select new Model.Model.Talent
{
Id = t.Id,
FirstName = t.FirstName,
LastName = t.LastName,
TalentLanguages = new LazyList<Model.Model.TalentLanguage>(tLanguage),
LanguagesString = t.TalentLanguages.ToLanguageNameString(_LanguageRepository.GetLanguages()),
City = t.City,
};
return ts.AsQueryable<Model.Model.Talent>();
}
public IQueryable<Model.Model.TalentLanguage> GetTalentLanguages(int iTalentId)
{
var q = from y in this.talentLanguageList
let Languages = _LanguageRepository.GetLanguages()
where y.TalentId == iTalentId
select new Model.Model.TalentLanguage
{
TalentLanguageId = y.TalentLanguageId,
TalentId = y.TalentId,
LanguageId = y.LanguageId,
Language = Languages.Where(x => x.LanguageId == y.LanguageId).SingleOrDefault()
};
return q.AsQueryable<Model.Model.TalentLanguage>();
}
}
If you're trying to find entries which match all of those criteria, you just need multiple where clauses:
private static readonly char[] SplitDelimiters = " ".ToCharArray();
private IQueryable<Talent> BasicSearch(string search)
{
// Just replacing " " with " " wouldn't help with "a b"
string[] terms = search.Trim()
.ToLower()
.Split(SplitDelimiters,
StringSplitOptions.RemoveEmptyEntries);
IQueryable<Talent> query = _repository.GetTalents();
foreach (string searchTerm in terms)
{
query = AddBasicSearch(query, searchTerm);
}
return query;
}
private IQueryable<Talent> AddBasicSearch(IQueryable<Talent> query, string s)
{
return query.Where(tal =>
tal.EyeColor.ToString().ToLower().Contains(s)
|| tal.FirstName.ToLower().Contains(s)
|| tal.LastName.ToLower().Contains(s)
|| tal.LanguagesString.ToLower().Contains(s)
);
}