HttpStringContent Making JSON Invalid? - json

httpClient = new HttpClient();
stringContent = new HttpStringContent(postBody, UnicodeEncoding.Utf8, "application/json");
httpResponse = await httpClient.PostAsync(uri, stringContent);
String responseString = await httpResponse.Content.ReadAsStringAsync();
Writing a UWP app and trying to send JSON data to a web server. In another method when I serialize an object to JSON postBody = JsonConvert.SerializeObject(parentModel);, I get valid JSON:
"{\"ParentId\":\"uwp#test.com\",\"ParentPrimaryId\":\"uwp#test.com\",\"ParentPassword\":\"n78mG2LB18ANtzr7gd2X/fILNELjbjOMuTWbhWoDvcg=\",\"ParentFirstName\":\"Bill\",\"ParentLastName\":\"Gates\",\"AddChildDistrictId\":\"\",\"RemoveChildDistrictId\":\"\",\"ParentToken\":null,\"ParentDistrictId\":\"\",\"ParentChildDistricts\":\"\",\"AppPlatform\":\"Windows 10.0.15063.138\",\"AppVersion\":10000,\"ParentAccountStatus\":1,\"ParentStatusCode\":0,\"ParentFailedSignInAttempt\":0}"
However, when I pass the post body to HttpStringContent, it gives me:
{{"ParentId":"uwp#test.com","ParentPrimaryId":"uwp#test.com","ParentPassword":"n78mG2LB18ANtzr7gd2X/fILNELjbjOMuTWbhWoDvcg=","ParentFirstName":"Bill","ParentLastName":"Gates","AddChildDistrictId":"","RemoveChildDistrictId":"","ParentToken":null,"ParentDistrictId":"","ParentChildDistricts":"","AppPlatform":"Windows 10.0.15063.138","AppVersion":10000,"ParentAccountStatus":1,"ParentStatusCode":0,"ParentFailedSignInAttempt":0}}
Which is invalid JSON. Is this what is being sent? Why does it add the extra outer brace and remove the beginning quotation marks?

I suspect those are actually the same string at the byte level, and the difference is in how Visual Studio is displaying them to you.
The first example is a syntactically correct C# literal string, surrounded in quotes with internal quotes escaped. The actual string of course doesn't contain backslash characters or starting/ending quotes; those are just required to represent the string in C#.
The second example looks like how Visual Studio's debugging tools display an object and its contents. In this case, the outer {} are how VS tells you it's a object; those characters aren't in the actual string.
So again, I think they are byte-for-byte the same actual string, just represented differently by the IDE.

Related

Calling an API returns expected JSONArray, found JSONObject

I'm calling an API from Go and trying to push json string data from another api call into it.
I can hand craft the calls using a payload like
payload := strings.NewReader('[{"value1":333, "value2":444}]'
and everything is happy.
I'm now trying to covert this to take the json string {"value1":333, "value2":444} as an input parameter of type string to a function, but when I try and use that as the payload, the api is responding with
expected type: JSONArray, found: JSONObject
I naively tried setting the input to the function as []string and appending the data to an array as the input, but then strings.NewReader complained that it was being fed an array.. which is was.
I'm at a loss to work out how to convert a string of json into a json array that the api will be happy with.
I tried just surrounding the string with [] but the compiler threw a fit about incorrect line termination.
Must have been doing something wrong with the string, surrounding the {} with [] let the function pass the data, but there must be a better way than this.
Any ideas, or am I making this harder than it should be?
You were on the right track with the brackets, but you actually need to append the characters to the string. For example:
str := `{"value1":333, "value2":444}`
str = "[" + str + "]"
// [{"value1":333, "value2":444}]
https://play.golang.org/p/rWHCLDCAngd
If you use brackets outside a string or rune literal, then it is parsed as Go language syntax.

Enumerating of JObject of NewtonSoft.Json loses '\' character in C#

I would like to parse json string using JObject.Parse() of NewtonSoft.Json. Assume that the json string is like this:
{"json":"{\"count\":\"123\"}"}
The result of jObject.First.ToString() is "json": "{\"count\":\"123\"}".
The result of jObject["json"].ToString() is {"count":"123"}. Enumerating gets the same result as this.
The testing code I used is like this.
[TestMethod()]
public void JsonParseTest()
{
var json = "{\"json\":\"{\\\"count\\\":\\\"123\\\"}\"}";
var jObject = JObject.Parse(json);
Console.WriteLine($"json : {json}");
Console.WriteLine($"jObject.First.ToString() : {jObject.First}");
Console.WriteLine($"jObject[\"json\"].ToString() : {jObject["json"]}");
}
We can see that enumerating of jObject will lose the character '\'. What is the problem? I would be appreciated for any suggestion :)
EDIT 1
The version of NewtonSoft is 12.0.3 released in 2019.11.09.
The parser isn't loosing anything. There is no literal \ in your example. The backslashes are purely part of the JSON syntax to escape the " inside the string vlue. The value of the key json is {"count":"123"}.
If you want to have backslashes in that value (however I don't see why you would want that), then you need add them, just like you added them in your C# string (C# and JSON happen to have the same escaping mechanism):
{"json":"{\\\"count\\\":\\\"123\\\"}"}
with leads to the C# code:
var json = "{\"json\":\"{\\\\\\\"count\\\\\\\":\\\\\\\"123\\\\\\\"}\"}";

Ruby parse string to json

So I have some json that looks like this, which I got after taking it out of some other json by doing response.body.to_json:
{\n \"access_token\": \"<some_access_token>\",\n \"token_type\": \"Bearer\",\n \"expires_in\": 3600,\n \"id_token\": \<some_token>\"\n}\n"
I want to pull out the access_token, so I do
to_return = {token: responseJson[:access_token]}
but this gives me a
TypeError: no implicit conversion of Symbol into Integer
Why? How do I get my access token out? Why are there random backslashes everywhere?
to_json doesn't parse JSON - it does the complete opposite: it turns a ruby object into a string containing the JSON representation of that object is.
It's not clear from your question what response.body is. It could be a string, or depending on your http library it might have already been parsed for you.
If the latter then
response.body["access_token"]
Will be your token, if the former then try
JSON.parse(response.body)["access_token"]
Use with double quotes when calling access_token. Like below:
to_return = {token: responseJson["access_token"]}
Or backslashes are escaped delimiters and make sure you first parse JSON.

Webapi return json with extra double slashes for a path property

I am using asp.net webapi and returning json response. One of the property in the json response has got a path field. When i check in Console.WriteLine i get the values without additional double slashes. But the json response in postman contains extra double slashes.
Expected:
\\test.com\cax\mef\160704\160704Z003.abc
But in the json response the output i am getting is:
"path": "\\\\test.com\\cax\\mef\\160704\\160704Z004.abc"
And my json settings in webapi.config:
var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
var settings = jsonFormatter.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
Can anyone help me what is the problem and how to solve this?
Why i am getting extra double slashes?
Thanks
The added slashes are their as Escape characters.
This Could be caused when you asign the URL to the Variable before you return the response via the Webapi. Eg:
xObj.path = urlPath;
----------------
xObj.path = urlPath.ToString();
It All Depends on where and how you Assigned them.. If they are coming for a Database they could have also Been Stored Like that.
it could also just be the IDE showing it to you Like that. This Often Just Adds the Escape characters to the interpretation of the value.. but when the value is used they are no longer present.
this is how you parse the JSON
var jsonResponse = '{ "firstName":"John" , "lastName":"Doe", "path" : "/test/test/adasdasd.com" }';
var obj = JSON.parse(jsonResponse);
console.log(obj);
You Will note that my Example doesn't have the double slashes. That is because if you use the response directly it wont have any either.

Strange Base64 encode/decode problem

I'm using Grails 1.3.7. I have some code that uses the built-in base64Encode function and base64Decode function. It all works fine in simple test cases where I encode some binary data and then decode the resulting string and write it to a new file. In this case the files are identical.
But then I wrote a web service that took the base64 encoded data as a parameter in a POST call. Although the length of the base64 data is identical to the string I passed into the function, the contents of the base64 data are being modified. I spend DAYS debugging this and finally wrote a test controller that passed the data in base64 to post and also took the name of a local file with the correct base64 encoded data, as in:
data=AAA-base-64-data...&testFilename=/name/of/file/with/base64data
Within the test function I compared every byte in the incoming data parameter with the appropriate byte in the test file. I found that somehow every "+" character in the input data parameter had been replaced with a " " (space, ordinal ascii 32). Huh? What could have done that?
To be sure I was correct, I added a line that said:
data = data.replaceAll(' ', '+')
and sure enough the data decoded exactly right. I tried it with arbitrarily long binary files and it now works every time. But I can't figure out for the life of me what would be modifying the data parameter in the post to convert the ord(43) character to ord(32)? I know that the plus sign is one of the 2 somewhat platform dependent characters in the base64 spec, but given that I am doing the encoding and decoding on the same machine for now I am super puzzled what caused this. Sure I have a "fix" since I can make it work, but I am nervous about "fixes" that I don't understand.
The code is too big to post here, but I get the base64 encoding like so:
def inputFile = new File(inputFilename)
def rawData = inputFile.getBytes()
def encoded = rawData.encodeBase64().toString()
I then write that encoded string out to new a file so I can use it for testing later. If I load that file back in as so I get the same rawData:
def encodedFile = new File(encodedFilename)
String encoded = encodedFile.getText()
byte[] rawData = encoded.decodeBase64()
So all that is good. Now assume I take the "encoded" variable and add it to a param to a POST function like so:
String queryString = "data=$encoded"
String url = "http://localhost:8080/some_web_service"
def results = urlPost(url, queryString)
def urlPost(String urlString, String queryString) {
def url = new URL(urlString)
def connection = url.openConnection()
connection.setRequestMethod("POST")
connection.doOutput = true
def writer = new OutputStreamWriter(connection.outputStream)
writer.write(queryString)
writer.flush()
writer.close()
connection.connect()
return (connection.responseCode == 200) ? connection.content.text : "error $connection.responseCode, $connection.responseMessage"
}
on the web service side, in the controller I get the parameter like so:
String data = params?.data
println "incoming data parameter has length of ${data.size()}" //confirm right size
//unless I run the following line, the data does not decode to the same source
data = data.replaceAll(' ', '+')
//as long as I replace spaces with plus, this decodes correctly, why?
byte[] bytedata = data.decodeBase64()
Sorry for the long rant, but I'd really love to understand why I had to do the "replace space with plus sign" to get this to decode correctly. Is there some problem with the plus sign being used in a request parameter?
Whatever populates params expects the request to be a URL-encoded form (specifically, application/x-www-form-urlencoded, where "+" means space), but you didn't URL-encode it. I don't know what functions your language provides, but in pseudo code, queryString should be constructed from
concat(uri_escape("data"), "=", uri_escape(base64_encode(rawBytes)))
which simplifies to
concat("data=", uri_escape(base64_encode(rawBytes)))
The "+" characters will be replaced with "%2B".
You have to use a special base64encode which is also url-safe. The problem is that standard base64encode includes +, / and = characters which are replaced by the percent-encoded version.
http://en.wikipedia.org/wiki/Base64#URL_applications
I'm using the following code in php:
/**
* Custom base64 encoding. Replace unsafe url chars
*
* #param string $val
* #return string
*/
static function base64_url_encode($val) {
return strtr(base64_encode($val), '+/=', '-_,');
}
/**
* Custom base64 decode. Replace custom url safe values with normal
* base64 characters before decoding.
*
* #param string $val
* #return string
*/
static function base64_url_decode($val) {
return base64_decode(strtr($val, '-_,', '+/='));
}
Because it is a parameter to a POST you must URL encode the data.
See http://en.wikipedia.org/wiki/Percent-encoding
paraquote from the wikipedia link
The encoding used by default is based
on a very early version of the general
URI percent-encoding rules, with a
number of modifications such as
newline normalization and replacing
spaces with "+" instead of "%20"
another hidden pitfall everyday web developers like myself know little about