Processing json string in mql4 - mql4

I have received the following string:
{"records":[{"id":"rec4haaOncoQniu8U","fields":{"orders1":5},"createdTime":"2020-02-08T09:08:22.000Z"}]}
I am not understanding how I can process and separate the values of the json in mql4 using the "JAson.mqh " library, located here: https://www.mql5.com/en/code/13663
I need the values of "orders" located under "fields" , value = 5.
the only "KEYS" that changes are the keys within the "fields" values.
i would like to be able to get the values with something like this:
string value1 = Result[0].["fields"].["orders1"]; //5
string value2 = Result[0].["fields"].["orders2"];
Please let me know what I can do.

You can get the value using the following format. Note that it has to be casted to a type. (I have casted it to int as it is the type it is in the JSON, but you can cast it to string as well)
int value1 = json["records"][0]["fields"]["orders1"].ToInt(); // if you want to make it a string use ToStr() instead of ToInt()
Here is a full example of what I did
string jsonString = "{\"records\": [{\"id\": \"rec4haaOncoQniu8U\",\"fields\": {\"orders1\": 5 }\"createdTime\": \"2020-02-08T09:08:22.000Z\"}]}";
if(json.Deserialize(jsonString))
Alert(json["records"][0]["fields"]["orders1"].ToInt());
Hope it helped.

Related

Format JSON string to iOS Dictionary string with =

First off, what do we call a dictionary with a format like this in iOS?
(
{
name = "Apple";
value = "fruit-1";
},
{
name = "Banana";
value = "fruit-2";
}
)
And for my main question. I somehow need to format a string of JSON, like this:
[{"name":"Apple","value":"fruit-1"},{"name":"Banana","value":"fruit-2"}]
into whatever that format is called (of the string above).
For context, the existing approach of my project uses CoreData where the Server response (which uses the mystery format above) gets saved locally as a String, and I want to follow that format.
EDIT: for more context, I really need to just get the first format into the database because a module of a project was built to read the data with that format (e.g. make use of NSString.propertyList()).
Using a library called ios hierarchy viewer, I can see the saved object in the device.
Original format, server json to db (core data) in Objective-C:
What I've been trying to do in Swift, server json to local using JSONSerialization:
First off, what do we call a dictionary with a format like this in iOS?
According to the documentation of NSString.propertyList(), that's a "text representation of a property list".
It's a wonky, non-standard pretty-printing obtained by calling NSArray.description or NSDictionary.description.
Here's an example that shows a round-trip of data:
// The opening `{` indentation is fucky, but that's how it's generated.
let inputPropertyList = """
(
{
name = "Apple";
value = "fruit-1";
},
{
name = "Banana";
value = "fruit-2";
}
)
"""
// The result is an `Any` because we don't know if the root structure
// of the property list is an array or a dictionary
let deserialized: Any = inputPropertyList.propertyList()
// If you want the description in the same format, you need to cast to
// Foundation.NSArray or Foundation.NSDictionary.
// Swift.Array and Swift.Dictionary have a different description format.
let nsDict = deserialized as! NSArray
let roundTrippedPropertyList = nsDict.description
print(roundTrippedPropertyList)
assert(roundTrippedPropertyList == inputPropertyList)
The second format you show is what you get when you display an object in the debug console. That's the output of the object's description property. It isn't a "JSON string", exactly.
If you want to convert your objets to a true JSON string, see below.
As Alexander pointed out, the first string in your question is the output from NSString's propertyList() function. The format looks quite similar to "pretty-printed" JSON, but it's different enough that it it won't work that way.
The `propertyList() function is a debugging-only function, and I don't know of an existing way to parse that back into objects. If that is the string that's being sent by your server, your server is broken. If that's what you see in core data when you log the contents of a field, it's probably a misunderstanding on your part.
To convert an object to pretty JSON, see this answer, where I created an extension to the Encodable format that implements a property "prettyJSON":
extension Encodable {
var prettyJSON: String {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
guard let data = try? encoder.encode(self),
let output = String(data: data, encoding: .utf8)
else { return "Error converting \(self) to JSON string" }
return output
}
}
That should work for any object that supports the Encodable protocol. (And your object should.)

String cast vs String unwrapping

I am trying to compare string values. String values are stored in Dictionary.
When I unwrap data like this:
let type:String = basicBlk["type"] as! String
and compare
print (type.lowercaseString == "minion")
result is true
While if I cast like this:
let type:String = String(basicBlk["type"])
and compare
print (type.lowercaseString == "minion")
result is false
I would like to understand what exactly is the difference.
This
let type:String = String(basicBlk["type"])
Converts the optional value into a string that looks like:
Optional("Minion")
And when you convert that string to lower case, it looks like:
optional("minion")
The issue is that you're creating a string representation of an optional value, and it's including the string "Optional(" and string ")" in the resulting value.
Just print type for both of your two examples and you'll see what I mean.

Formatting strings in Swift

In some languages, like C# for example, you can create a string in the following way:
"String {0} formatted {1} "
And then format it with String.format by passing in the values to format.
The above declaration is good, because you don't have to know of what type its parameters are when you create the string.
I tried to find similar approach in Swift, but what I found out was something like the following format:
"String %d formatted %d"
which requires you to format the string with String(format: , parameters). This is not good because you would also have to know parameter types when declaring the string.
Is there a similar approach in Swift where I wouldn't have to know the parameter types?
Use this one:
let printfOutput = String(format:"%# %2.2d", "string", 2)
It's the same as printf or the Obj-C formatting.
You can also mix it in this way:
let parm = "string"
let printfOutput = String(format:"\(parm) %2.2d", 2)
Edit: Thanks to MartinR (he knows it all ;-)
Be careful when mixing string interpolation and formatting. String(format:"\(parm) %2.2d", 2) will crash if parm contains a percent character. In (Objective-)C, the clang compiler will warn you if a format string is not a string literal.
This gives some room for hacking:
let format = "%#"
let data = "String"
let s = String(format: "\(format)", data) // prints "String"
In contrast to Obj-C which parses the format string at compile time, Swift does not do that and just interprets it at runtime.
In Swift, types need to conform to the CustomStringConvertible protocol in order to be used inside strings. This is also a requirement for the types used in string interpolation like this:
"Integer value \(intVal) and double value \(doubleVal)"
When you understand the CustomStringConvertible, you can create your own function to fulfill your needs. The following function formats the string based on the given arguments and prints it. It uses {} as a placeholder for the argument, but you can change it to anything you want.
func printWithArgs(string: String, argumentPlaceHolder: String = "{}", args: CustomStringConvertible...) {
var formattedString = string
// Get the index of the first argument placeholder
var nextPlaceholderIndex = string.range(of: argumentPlaceHolder)
// Index of the next argument to use
var nextArgIndex = 0
// Keep replacing the next placeholder as long as there's more placeholders and more unused arguments
while nextPlaceholderIndex != nil && nextArgIndex < args.count {
// Replace the argument placeholder with the argument
formattedString = formattedString.replacingOccurrences(of: argumentPlaceHolder, with: args[nextArgIndex].description, options: .caseInsensitive, range: nextPlaceholderIndex)
// Get the next argument placeholder index
nextPlaceholderIndex = formattedString.range(of: argumentPlaceHolder)
nextArgIndex += 1
}
print(formattedString)
}
printWithArgs(string: "First arg: {}, second arg: {}, third arg: {}", args: "foo", 4.12, 100)
// Prints: First arg: foo, second arg: 4.12, third arg: 100
Using a custom implementation allows you to have more control over it and tweak its behavior. For example, if you wanted to, you could modify this code to display the same argument multiple times using placeholders like {1} and {2}, you could fill the arguments in a reversed order, etc.
For more information about string interpolation in Swift: https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-ID292

Unexpected result from call to Newtonsoft.Json from F#

I am not getting the expected result from this F# code. I would expect t to contain values as a result of the call to JsonSchema.Parse(json) but instead it is empty. What am I doing wrong?
open Newtonsoft.Json
open Newtonsoft.Json.Schema
let json = """{
"Name": "Bad Boys",
"ReleaseDate": "1995-4-7T00:00:00",
"Genres": [
"Action",
"Comedy"
]
}"""
[<EntryPoint>]
let main argv =
let t = JsonSchema.Parse(json)
0 // return an integer exit code
As John Palmer points out, JsonSchema.Parse parses a JSON schema, but from your question, it looks as though you want to parse a normal JSON value. This is possible with JsonConvert.DeserializeObject:
let t = JsonConvert.DeserializeObject json
However, the signature of DeserializeObject is to return obj, so that doesn't particularly help you access the values. In order to do so, you must cast the return value to JObject:
let t = (JsonConvert.DeserializeObject json) :?> Newtonsoft.Json.Linq.JObject
let name = t.Value<string> "Name"
Json.NET is designed to take advantage of C#'s dynamic keyword, but the exact equivalent of that isn't built into F#. However, you can get a similar syntax via FSharp.Dynamic:
open EkonBenefits.FSharp.Dynamic
let t = JsonConvert.DeserializeObject json
let name = t?Name
Notice the ? before Name. Keep in mind that JSON is case-sensitive.
Now, name still isn't a string, but rather a JValue object, but you can get the string value by calling ToString() on it, but you can also use JValue's Value property, which can be handy if the value is a number instead of a string:
let jsonWithNumber = """{ "number" : 42 }"""
let t = JsonConvert.DeserializeObject jsonWithNumber
let actual = t?number?Value
Assert.Equal(42L, actual)
I recommend to use Json type provider instead.

How can I convert a string to a char array in ActionScript 3?

How do you convert a string into a char array in ActionScript 3.0?
I tried the below code but I get an error:
var temp:ByteArray = new ByteArray();
temp = input.toCharArray();
From the error, I understand that the toCharArray() function cannot be applied to a string (i.e in my case - input). Please help me out. I am a beginner.
I am not sure if this helps your purpose but you can use String#split():
If you use an empty string ("") as a delimiter, each character in the string is placed as an element in the array.
var array:Array = "split".split("");
Now you can get individual elements using index
array[0] == 's' ; array[1] == 'p' ....
Depending on what you need to do with it, the individual characters can also be accessed with string.charAt(index), without splitting them into an array.

Resources