JSON.parse Map want String get integer - json

Dart is great, it's like, well, programming. Also the IDE is great.
I have encountered what appears to me to be a problem (for me) with the Dart
JSON.parse function. The problem appears to me to be that if a string
is an integer, it creates an integer in the Map. This may not be desirable
because there could be situations where string fields contain numeric.
eg. an address that contains just the street number. Or, perhaps I am
simply doing something wrong.
The line of code that exposes the possible problem is :
String sId = mAcctData['I_Id'];
I presume that there is a logical solution to this, and if so I would
appreciate being advised
httpSubmitAccountNrLoadEnd(HttpRequest httpReq) {
String sResponse = null;
if (httpReq.status != 200) {
print('On Http Submit Account Nr. There was an error : status = ${httpReq.status}');
} else {
print("On Return from Http Submit Account Nr. no error - status = ${httpReq.status}");
sResponse = httpReq.responseText;
}
print("Response From Submit Account Nr. = ${sResponse}"); // print the received raw JSON text
Map mAcctData = JSON.parse(sResponse);
print ("Json data parsed to map");
print ("Map 'S_Custname' = ${mAcctData['S_Custname']}");
String sCustName = mAcctData['S_Custname'];
print ("About to extract sId from Map data");
String sId = mAcctData['I_Id'];
print ("sId has been extracted from Map data");
String sAcctNr = mAcctData['I_AcctNr'];
String sAcctBal = mAcctData['I_AcctBal'];
The following is the console output.
The line that shows the problem that I have is:
Exception: type 'int' is not a subtype of type 'String' of 'sId'.
About to send http message
On Return from Http Submit Account Nr. no error - status = 200
Response From Submit Account Nr. = {"S_Custname":"James Bond","I_Id":1,"I_Acctnr":123456789,"I_AcctBal":63727272,"I_AvailBal":0}
Json data parsed to map
Map 'S_Custname' = James Bond
About to extract sId from Map data
Exception: type 'int' is not a subtype of type 'String' of 'sId'.
Stack Trace: #0 httpSubmitAccountNrLoadEnd (http://127.0.0.1:3030/C:/Users/Brian/dart/transact01/transact01.dart:75:31)
1 submitAccountNr.submitAccountNr. (http://127.0.0.1:3030/C:/Users/Brian/dart/transact01/transact01.dart:33:59)
Exception: type 'int' is not a subtype of type 'String' of 'sId'.
Stack Trace: #0 httpSubmitAccountNrLoadEnd (http://127.0.0.1:3030/C:/Users/Brian/dart/transact01/transact01.dart:75:31)
1 submitAccountNr.submitAccountNr. (http://127.0.0.1:3030/C:/Users/Brian/dart/transact01/transact01.dart:33:59)
Questions:
Is there a solution to this? (eg. force JSON.parse to create strings)
Is there a better way to handle this? (eg. extract data directly from the JSON string)

From what I see in your sResponse mAcctData['I_Id'] is really an int :
{
"S_Custname": "James Bond",
"I_Id": 1,
"I_Acctnr": 123456789,
"I_AcctBal": 63727272,
"I_AvailBal": 0
}
So if you want to get a String for mAcctData['I_Id'] you can use int.toString() :
String sId = mAcctData['I_Id'].toString();

Just turn your integers into strings if you want them to be like that:
{
"S_Custname": "James Bond",
"I_Id": "1",
"I_Acctnr": "123456789",
"I_AcctBal": "63727272",
"I_AvailBal": "0"
}
Now it should work fine. Alternatively, use .toString() to convert the integers into strings.

Related

JSON decoding from stream in Kotlin

I have a server set up to send messages over a local host port. I am trying to decode the serialized json messages sent by the server and get this error.
Error decoding message: kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 55: Expected EOF after parsing, but had instead at path: $
JSON input: .....mber":13,"Timestamp":5769784} .....
The Racer State messages are formatted in JSON as follows: { “SensorId”: “value”, “RacerBibNumber” : “value”, “Timestamp” : “value” }, where the value’s are character string representations of the field values. I have also tried changing my RacerStatus Class to take String instead of Int but to a similar error. Am I missing something here? The symbol that is missing in the error was not able to be copied over so I know it's not UTF-8.
I have also added
val inputString = bytes.toString(Charsets.UTF_8)
println("Received input: $inputString")
This gets
Received input: {"SensorId":0,"RacerBibNumber":5254,"Timestamp":3000203}
with a bunch of extraneous symbols at the end.
data class RacerStatus(
var SensorId: Int,
var RacerBibNumber: Int,
var Timestamp: Int
) {
fun encode(): ByteArray {
return Json.encodeToString(serializer(), this).toByteArray()
}
companion object {
fun decode(bytes: ByteArray): RacerStatus {
print(bytes[0])
try {
val mstream = ByteArrayInputStream(bytes)
return Json.decodeFromStream<RacerStatus>(mstream)
} catch (e: SerializationException) {
println("Error decoding message: $e")
return RacerStatus(0, 0, 0)
}
// return Json.decodeFromString(serializer(), mstream.readBytes().toString())
}
}
}
So I found an answer to my question. I added a regex to include just the json components I know my json contains.
val str = bytes.toString(Charsets.UTF_8)
val re = Regex("[^A-Za-z0-9{}:,\"\"]")
return Json.decodeFromString<RacerStatus>(re.replace(str,""))
I thought that Charsets.UTF_8 would remove the misc characters but it did not. Is there a more intiuative solution? Also is there a regex that would cover all possible values in json?

how to get value from json via variable in typescript?

supposing I have to read some data from some json files(i18n), every json file may look like:
{
"foo": "1",
"bar": "2",
...
}
I don't know how many fields this json have(it can be expanded), but it's fields look like
{
[prop: string]: string
}
besides, all the json files share the same fields.
when I try to read a value from this json via:
//a can be expanded, I'm not sure how many fileds does it have
let a = {
name: "dd",
addr: "ee",
}
//I'm confident a has a field "name"
let b = "name";
console.log(a[b]);
the error message is:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type
how could I fix it?
The error you're encountering is because the keys in a is not just any string (in fact, it can only be "name" or "add"), but b can be a string of any arbitrary value. If you are very sure that b represents a key found in the object a, you can hint TypeScript as such:
let b: keyof typeof a = "name";
Attempting to assign any arbitrary string value to b will lead to an error:
// This will cause an error
let b: key typeof a = "foobar";
See proof-of-concept on TypeScript Playground.

How do I serialize and deserialize a tuple in Rust using Serde?

I have a tuple consisting of an String and a Uuid that I serialize using serde_json:
let log_and_id = (String::from("Test string"), test_id);
let log_and_id_serialized = serde_json::to_string(&log_and_id)
.expect("Serialization failed");
//After serialization (debug print): "[\"Test string\",\"32a8e12d-69d2-421d-a52e-1ee76cc03ed5\"]"
Then I transfer this serialized value over the network and receive a BytesMut (serialized_tuple) on the other end, which I try to deserialize:
//Bytesmut value (debug print): b"\"[\\\"Test string\\\",\\\"32a8e12d-69d2-421d-a52e-1ee76cc03ed5\\\"]\""
let (log, operation_state_id) = serde_json::from_slice::<(String, Uuid)>(&serialized_tuple)?;
But I get the following error:
ERROR actix_http::response] Internal Server Error: SerdeError(Error("invalid type: string \"[\\\"Test string\\\",\\\"32a8e12d-69d2-421d-a52e-1ee76cc03ed5\\\"]\", expected a tuple of size 2", line: 1, column: 68))
(De)serializing single objects this way used to work in other parts of this code, so what could cause it to fail when used with tuples?
You don't have a serialized tuple, but a serialized serialized tuple.
I mean the serialization of the tuple, which was a JSON string, was again serialized.
You can check this with this code (playground):
let serialized_tuple = b"\"[\\\"Test string\\\",\\\"32a8e12d-69d2-421d-a52e-1ee76cc03ed5\\\"]\"";
let serialized_tuple: String = serde_json::from_slice(serialized_tuple).unwrap();
let (log, operation_state_id) = serde_json::from_slice::<(String, String)>(serialized_tuple.as_bytes()).unwrap();
which produces the desired tuple.
Of course, rather than deserializing twice, you should remove the unnecessary serialization from your application (it's not in the code you've shown).

parse json response to typescript class

i know there are multiple similar topics, however trying their solutions doesn't give me expected result.
Input json string
data:"{"message": "{\"type\":\"CONTROL\",\"command\":\"REQUEST_STATUS_ALL\"}"}"
object declaration/parse:
const msg: Message = <Message>JSON.parse(data.data);
output:
{message: "{"type":"CONTROL","command":"REQUEST_STATUS_ALL"}"}
-values are not properly assigned, but instead in a text form.
the same object looks like this if it's initialized manually(in TS):
Message {type: "CONTROL", status: undefined, command: "REQUEST_STATUS_ALL", body: undefined}
What is the correct way to parse that json string into the Message object?
Thank you!
It seems the value for message was improperly encoded as a string. Calling JSON.parse a second time on the message property will get the result you want, though you might want to fix the underlying cause of the improperly encoded data instead.
parseMessage(data: string) {
const msgTemp = JSON.parse(data);
msgTemp.message = JSON.parse(msgTemp.message);
return <Message>msgTemp;
}
const msg = parseMessage(data.data);

Golang Error Types are empty when encoded to JSON

I'm trying to encode some JSON for a REST api, everything is working fine except for some errors. For example, with this struct:
type TemplateResponse struct {
Message string
Error error
Template Template
}
Encoded with this data:
res := TemplateResponse{"Template not found.", fmt.Errorf("There is no template on this host with the name " + vars["name"]), Template{}}
json.NewEncoder(w).Encode(res)
Returns:
{
"Message": "Template not found.",
"Error": {},
"Template": {
"Name": "",
"Disabled": false,
"Path": "",
"Version": ""
}
}
I'm getting this seemingly randomly across my application, where 'error' types are being returned as empty. Any ideas?
Thanks!
Because error is just an interface. It may hold a value of any concrete type that implements it.
In your example you used fmt.Errorf() to create an error value. That calls errors.New() which returns a pointer to a value of the unexported errors.errorString struct. Its definition is:
type errorString struct {
s string
}
This struct value will be marshaled, but since it has no exported fields (only exported fields are marshaled), it will be an empty JSON object: {}.
The "fix" is: don't marshal values of "general" interfaces, relying on that the dynamic values can be marshaled into JSON meaningfully. Instead you should add a field that stores the error string (the result of error.Error()), and omit the Error error field from marshaling, e.g.:
type TemplateResponse struct {
Message string
Error error `json:"-"`
ErrorMsg string
Template Template
}
Of course then you also need to set / fill the ErrorMsg field before marshaling.
Or if you don't need to store the error value in the struct, remove that field completely:
type TemplateResponse struct {
Message string
ErrorMsg string
Template Template
}
If you still want to keep the Error error field (and not the ErrorMsg field), then you need to implement a custom marshaling logic by implementing the json.Marshaler interface where you can "convert" the error value to a meaningful string for example (or into another value that can be marshaled properly).