TryGetInt32 throws System.InvalidOperationException - json.net

Call me crazy, but I was under the impression that there was a convention of try which meant give it a go, but if you can't then get back to me and let me know that it was a "no-go".
I have recently started a new project and I have decided to use System.Text.Json instead of Newtonsoft since it has been out for a while now and I like to play with new things.
I have the following bit of code in a JsonConverter:
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
if (jsonDoc.RootElement.TryGetInt32(out int number))
{
}
}
When it is a number, it works awesomely, but when it is anything but a number, it throws as if I was calling GetInt32().
In the custom converter, I sometimes get a number back, but I also can get an object back which contains the number that I am expecting as well as a string. I thought that I would be able to test for this using the TryGetInt32 method.
I have two questions:
How could I test if I am getting the number back, or getting the number AND the string?, and
What is the difference between TryGetInt32(out int number) and GetInt32()?

TryGetInt32 throws exception if the value is not a number type.
It does not throw and returns false if the value is a number type but not a number kind convertible to int32.
I hope the following additional check helps:
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
if(jsonDoc.RootElement.ValueKind == JsonValueKind.Number &&
jsonDoc.RootElement.TryGetInt32(out int number))
{
}
}

first question :
using int.TryParse(variable,result) : this return bool and store variable if integer in result
example:
string json = "5";
int result;
if (int.TryParse(json, out result))
{
Console.WriteLine(result);
}
second question:
TryGetInt32(Int32) :Attempts to represent the current JSON number as an Int32 and return bool .
Getint32(): get specific value as int32 in this case you must be sure that the value is integer

Related

ELM QueryString parser dont compile

I am really trying to learn a bit of ELM, but my mind collapse at the query parse, my idea was to create a function to get a query string value by name something like: given an query string ?name=Neuber a function like this getParam "name" that would return Neuber
But its failing at most basic example, it doesn't even compile
page comes from here
routeParser comes from here
module Main exposing (..)
-- import Url.Parser exposing (Parser, (</>), (<?>), oneOf, s)
import Url.Parser.Query exposing (int, map, map2, string)
type alias QueryParams =
{ search : Maybe String
, page : Maybe Int
}
routeParser : Url.Parser.Query.Parser QueryParams
routeParser = map2 QueryParams (string "search") (int "page")
page : Url.Parser.Query.Parser Int
page = map (Result.withDefault 1) (int "page")
The error i got
-- TYPE MISMATCH ---------------- /a/long/way/to/project/src/Main.elm
The 2nd argument to `map` is not what I expect:
15| page = map (Result.withDefault 1) (int "page")
^^^^^^^^^^
This `int` call produces:
Url.Parser.Query.Parser (Maybe Int)
But `map` needs the 2nd argument to be:
Url.Parser.Query.Parser (Result x number)
Hint: I always figure out the argument types from left to right. If an argument
is acceptable, I assume it is “correct” and move on. So the problem may actually
be in one of the previous arguments!
The immediate problem is that int "page" will return a Maybe Int, but you're trying to use it with Result.withDefault, which, as the error message says, expects a Result. The fix for this is just to use Maybe.withDefault instead.

Iterating along a Dictionary in Swift 3

I am trying to iterate along a Dictionary in order to prune unconfirmed entries. The Swift 3 translation of the following Objective-C code does not work:
[[self sharingDictionary] enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
SharingElement* element=[[self sharingDictionary] objectForKey:key];
if (!element.confirmed){
dispatch_async(dispatch_get_main_queue(), ^{
[element deleteMe];
});
[[self sharingDictionary] performSelector:#selector(removeObjectForKey:) withObject:key
afterDelay:.2];
} else{
element.confirmed=NO;
}];
And so I tried using the following compact enumerated() method in this way:
for (key, element) in self.sharingDictionary.enumerated(){
if (!element.confirmed){
element.deleteMe()
self.perform(#selector(self.removeSharingInArray(key:)), with:key, afterDelay:0.2);
} else{
element.confirmed=false
}
}
Yet the compiler reports the following error while processing the usage of variable 'element':
Value of tuple type '(key: Int, value: SharingElement)' has no member
'confirmed'
Like 'element' took the full tuple father than the part of its competence.
Is the problem in the use of enumerated() or in the processing of the dictionary and how may I fix it?
Use element.value.confirmed. element is a tuple that contains both key and value.
But you probably just want to remove enumerated():
for (key, element) in self.sharingDictionary {
...
}
enumerated() takes the iteration and adds indices starting with zero. That's not very common to use with dictionaries.
This should do the trick,
localDictionary.enumerateKeysAndObjects ({ (key, value, stop) -> Void in
})
I ended up implementing the thing as:
DispatchQueue.global(attributes: .qosBackground).async{
for (key, element) in self.sharingDictionary{
if !element.confirmed{
DispatchQueue.main.async({
element.deleteMe()
self.removeSharingInArray(key:key)
})
} else{
element.confirmed=false
}
}
}
So to hopefully delete the object without changing the Dictionary while it is browsed, what used to crash the app, even if I do not know if it still the case.

Downcast element when reading from Dictionary in Swift

I'm trying to access an element a dictionary element and downcast it to a type other than AnyObject but keep getting the same compiler error: Could not find an overload for 'subscript' that accepts the supplied arguments.
I know I can just do this using two if statements like so:
if let x = dict["key"] {
if let y = x as? String {
// ...
}
}
But I feel there has to be a more elegant solution than this. The format that makes the most sense to me is:
if let x = dict["key"] as? String {
// ...
}
But this just results in the error, mentioned above. I've tried dozens of variations of this, but none of it seems to make any difference. Is this something that just can't be done in Swift?
The reason your desired formulation isn't working is that you're trying to unwrap two Optionals with a single as?. There are two Optionals because both the subscripting of your dictionary and the attempted cast to String return optional values. There isn't a way to do it in one if statement that will be runtime-safe, but there is a way:
if let x = dict["key"]! as? String {
println(x)
}
The problem is that if dict["key"] ends up being nil, the forced unwrapping will crash your app. Better to do it this way (you can skip the first if), even if it is an extra step:
let x: AnyObject? = dict["key"]
if let y = x as? String {
println(y)
}
The extra step is just the cost of working with a Dictionary<String, AnyObject> - if you can get your dictionary type more specific, you won't have to do it any more.
I was also struggling with this thing but then i fount out that optional chaining is the solution. Just use
if let x = dict["key"]? as? String {
println(x)
}
It gives you both the safety and compactness.
In the end I had to use this one-line solution:
if let name = jsonDict["name"] as AnyObject? as? String {
println("name is \(name)")
} else {
println("property was nil")
}

Storing results in a recursive function/ BST

I'm writing a bst function that would store all the keys within a given range as a String:
String rangeToString(TreeNode root,int low, int high, String result){
if(root==null) return "";
if(root.key>low)) rangeToString(root.leftChild, low, high,result);
if(root.key>=low && root.key.<=high) result+=root.key;
if(root.key<high) rangeToString(root.rightChild,low,high,result);
return result;
}
I'm basically doing an inorder traversal, adding values to the string when they're in range.
At the moment it returns a string that only contains the root key.
I know the problem is in my return statements, but I just can't seem to get how to implement the function without them.
Can anyone point me in the right direction please?
you can pass into your arguments a supplentary "accumulated up to now" list of strings (say you name it curlist). then when you return you return this curlist argument + .Add(your found key for this recursion level) and in the places you recursively call the fonction (rangeToString) you concatenate the result to the current list curlist (using Append or whatever).
pseudo code:
list<string> myRecursiveFunc(some args, list<string> curlist)
{
if (recursConditionOK)
curlist = curlist.Append(myRecusriveFunc, curlist);
return curlist;
}
First, you probably want to include a return on your recursion calls, since you are returning the results of your recursions:
String rangeToString(TreeNode root,int low, int high, String result){
if(root==null) return "";
if(root.key>low)) return rangeToString(root.leftChild, low, high,result);
if(root.key>=low && root.key.<=high) result+=root.key;
if(root.key<high) return rangeToString(root.rightChild,low,high,result);
return result;
}
I am suspicious of your conditions, so I would spend some time examining those... In fact, the return on the recursions are making an assumption about the structure of your conditions.
Also, one way of gathering parameters that's pretty intuitive is to use tail recursion and accumulate your results in your parameters.
You can read more here:
http://en.wikipedia.org/wiki/Tail_call
The key is that you are using your parameters themselves to gather the results, and when your function is done, you return your parameters (the ones that accumulate the results).

Simplest way to check if a string converted to a number is actually a number in actionscript

Not sure if this makes sense, but I need to check if a server value returned is actually a number. Right now I get ALL number values returned as strings
ie '7' instead of 7.
What's the simplest way to check if string values can actually be converted to numbers?
The easiest way to do this is to actually convert the string to a Number and test to see if it's NaN. If you look at the Flex API reference, the top-level Number() function says it will return NaN if the string passed to the method cannot be converted to a Number.
Fortunately, Flex (sort of) does this for you, with the isNaN() function. All you need to do is:
var testFlag:Boolean = isNaN( someStringThatMightBeANumber );
If testFlag is false, the string can be converted to a number, otherwise it can't be converted.
Edit
The above will not work if compiling in strict mode. Instead, you will need to first convert to Number and then check for NaN, as follows:
var testFlag:Boolean = isNaN( Number( someStringThatMightBeANumber ) );
Haven't tested this, but this should work:
if( isNaN(theString) ) {
trace("it is a string");
} else {
trace("it is a number");
}
If you are using AS3 and/or strict mode (as pointed out by back2dos), you will need to convert to number first in order for it to compile:
if( isNaN(Number(theString)) ) {
trace("it is a string");
} else {
trace("it is a number");
}
Most of the answers on this question have a major flaw in them. If you take Number(null) or Number(undefined) or Number(""), all will return 0 and will evaluate to "is a number". Try something like this instead:
function isANumber( val:* ):Boolean {
return !(val === null || val === "" || isNaN(val));
}
RegExp path :
function stringIsAValidNumber(s: String) : Boolean {
return Boolean(s.match(/^[0-9]+.?[0-9]+$/));
}
Here is another way to check if value can be converted to a number:
var ob:Object = {a:'2',b:3,c:'string'};
for( var v:* in ob){
var nr:Number = ob[v];
trace(ob[v]+" "+(nr === Number(nr)))
}
this will trace following:
2 true
3 true
string false
You can notice that in actionscript :
trace(int('7')); // will return 7
and
trace(int('a')); // will return 0
So except for zeros, you can actually now if a string is a number or not
this will try to convert your String to a Number, which essentially is a 64 bit floating point number:
var val:Number = Number(sourceString);
if sourceString is not a valid String representation of a Number, val will be NaN (not a number) ... you have check against that value with isNaN ... because val == NaN will return false for a reason that can't quite understand ... you can use int(val) == val to check, whether it is an integral value ...
greetz
back2dos
Put this into any function where you want only numbers to stayjoy_edit1 is a TextInput Object (spark)
//is a number check
if( isNaN(Number(joy_edit1.text)) ) {
joy_edit1.text = "";
return void;
}
function isANumber(__str:String):Boolean
{
return !isNaN(Number(__str));
}
You should use the native solution of Adobe:
parseInt and parseFloat methods.
Also read the isNaN description:
Returns true if the value is NaN(not a number). The isNaN() function
is useful for checking whether a mathematical expression evaluates
successfully to a number. The most common use of isNaN() is to check
the value returned from the parseInt() and parseFloat() functions. The
NaN value is a special member of the Number data type that represents
a value that is "not a number."
Here is a simple implementation:
function isANumber(value:String):Boolean {
return !isNaN(parseFloat(value));
}
typeof('7') == 'string'
typeof(7) == 'number'
Does that help?

Resources