I am trying to deserialize a json string received as a response from the service. The client is Windows Phone 7, in C#. I am using Json .NET - James Newton-King deserializor to directly convert the Json string to objects. But sometimes the Json string contains some comments information with double quotes (") in them and the deserializer fails and throws an error. Looks like this is an invalid Json string according to Jsonlint.
{
"Name": "A1",
"Description": "description of the "object" A1"
}
How to handle such Json String. If it is (\"), then it works. But I cannot replace all (") with (\") as there might be double quotes in other part of the json string. Is there any decode function of Json .Net?
It looks like HttpUtility.JavaScriptStringEncode might solve your issue.
HttpUtility.JavaScriptStringEncode(JsonConvert.SerializeObject(yourObject))
Just do:
yourJsonString = yourJsonString.Replace("\"", "\\u022");
object o = JSonConvert.Deserialize(yourJsonString);
\u022 is the ascii code for double quotes. So replacing quotes for \u022 will be recognized by your browser.
And use \ in "\u022" to make c# recognize backslash character.
Cheers
You can improving this.
static private T CleanJson<T>(string jsonData)
{
var json = jsonData.Replace("\t", "").Replace("\r\n", "");
var loop = true;
do
{
try
{
var m = JsonConvert.DeserializeObject<T>(json);
loop = false;
}
catch (JsonReaderException ex)
{
var position = ex.LinePosition;
var invalidChar = json.Substring(position - 2, 2);
invalidChar = invalidChar.Replace("\"", "'");
json = $"{json.Substring(0, position -1)}{invalidChar}{json.Substring(position)}";
}
} while (loop);
return JsonConvert.DeserializeObject<T>(json);
}
Example;
var item = CleanJson<ModelItem>(jsonString);
I had the same problem and i found a possible solution. The idea is to catch the JsonReaderException. This exception bring to you the attribute "LinePosition". You can replace this position to an empty character (' '). And then, you use this method recursively until whole json is fixed.
This is my example:
private JToken processJsonString(string data, int failPosition)
{
string json = "";
var doubleQuote = "\"";
try
{
var jsonChars = data.ToCharArray();
if (jsonChars[failPosition - 1].ToString().Equals(doubleQuote))
{
jsonChars[failPosition - 1] = ' ';
}
json = new string(jsonChars);
return JToken.Parse(json);
}
catch(JsonReaderException jsonException)
{
return this.processJsonString(json, jsonException.LinePosition);
}
}
I hope you enjoy it.
I would recommend to write email to server admin/webmaster and to ask them fix this issue with json.
But if this is impossible, you can write simple parse that finds nonescaped doublequotes inside doublequotes and escapes them. It will hardly be >20lines of code.
you can use newtonsoft library to convert it to object( to replace \" with "):
dynamic o = JObject.Parse(jsondata);
return Json(o);
Related
t fails to deserialize/prase this json, ive tried multiple combinations with different methods to try and make this work but nothing seems to do it...
The code im using
WebClient wc = new WebClient();
var json = (JObject)JsonConvert.DeserializeObject(wc.DownloadString("http://services.runescape.com/m=website-data/playerDetails.ws?names=[%22" + Username.Replace(" ", "%20") + "%22]&callback=jQuery000000000000000_0000000000&_=0"));
the json its trying to deserialize...
jQuery000000000000000_0000000000([{"isSuffix":true,"recruiting":false,"name":"Sudo Bash","clan":"Linux Overlord","title":"the Troublesome"}]);
In Json specification you can see that [ indicates the begining array of json objects while { indicates beginning of new json object.
Your json string starts with [ so it can contains more json objects ( because it's an array and it contains jQuery000000000000000_0000000000( which is your query string parameter. To get rid of the query string garbage you should find out the scheme of that garbage and then to process json object I would recommend you to deserialize your json string into List<JObject> using JsonConvert.DeserializeObject<T>() method if your json string starts with [ ( use standard type if it is starting with { );
Example :
string url = // url from #Darin Dimitrov answer
string response = wc.DownloadString(url);
// getting rid of the garbage
response = response.Substring(response.IndexOf('(') + 1);
response = response.Substring(0, response.Length - 1);
// should get rid of "jQuery000000000000000_0000000000(" and last occurence of ")"
JObject result = null;
if(response.StartsWith('['))
{
result = JsonConvert.DeserializeObject<List<JObject>>(response)[0];
}
else
{
result = JsonConvert.DeserializeObject<JObject>(response);
}
What you are trying to deserialize is not JSON but rather JSONP (which is JSON wrapped in a function call).
Remove this parameter from your query string:
&callback=jQuery000000000000000_0000000000
and you should be good to go with a properly formatted JSON:
var url = "http://services.runescape.com/m=website-data/playerDetails.ws?names=[%22" + Username.Replace(" ", "%20") + "%22]&_=0";
var json = (JObject)JsonConvert.DeserializeObject(wc.DownloadString(url));
If I have a json string, with one of its property values having a double quote in it, I am not able to parse it.
For example, if my object is { "Name" : "Six \" Pipe" } then the following gives me an error - Unexpected token P.
var str = '{ "Name" : "Six \" Pipe" }';
JSON.parse(str); //error
$.parseJSON(str); //error
The string is formed in a razor view as follows -
var str = new JavaScriptSerializer().Serialize(obj);
And then in JavaScript I am doing
var obj = JSON.parse('#(Html.Raw(str))');
How can I parse such strings?
You should escape the backslashes since in JS it will only \" will be converted to " and will make the JSON incorrect. The blackslash is discarded by javascript.
so the correct string would be-
var str = '{ "Name" : "Six \\" Pipe" }';
JSON.parse(str); //works
Edit:
So, if you want to create a literal backslash in JS, you have to escape it. You can do this while creating this string and double-escaping the key's value. One way to tackle this could be -
To html encode the strings (key values) just like: " instead of \" etc. This seems straight forward to me with .Net. I'm not sure but HttpServerUtility.HtmlEncode could help. Then on the javascript side you could be able to parse straight away- fiddle
I encountered same issue. After spending a lot of time trying to deal with that quotes I came to this solution
#{
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var obj = new {name = "\"Name1\""};
var objJson = serializer.Serialize(obj);
}
<script>
var jsObject = #Html.Raw(objJson);
</script>
I use json as js object without any parsing, html result will be like
<script>
var jsObject = {"name":"\"Name1\""} ;
</script>
which is correct JavaScript. Hope it will be helpfull for somebody
Is there a straightforward way of converting:
string str = "a=1,b=2,c=3";
into:
dynamic d = new { a = 1, b = 2, c = 3 };
I think I could probably write a function that splits the string and loops the results to create the dynamic object. I was just wondering if there was a more elegant way of doing this.
I think if you convert the "=" into ":" and wrap everything with curly brackets you'll get a valid JSON string.
You can then use JSON.NET to deserialize it into a dynamic object:
dynamic d = JsonConvert.DeserializeObject<dynamic>(jsonString);
You'll get what you want.
You may use Microsoft Roslyn (here's the all-in-one NuGet package):
class Program
{
static void Main(string[] args)
{
string str = "a=1,b=2,c=3,d=\"4=four\"";
string script = String.Format("new {{ {0} }}",str);
var engine = new ScriptEngine();
dynamic d = engine.CreateSession().Execute(script);
}
}
And if you want to add even more complex types:
string str = "a=1,b=2,c=3,d=\"4=four\",e=Guid.NewGuid()";
...
engine.AddReference(typeof(System.Guid).Assembly);
engine.ImportNamespace("System");
...
dynamic d = engine.CreateSession().Execute(script);
Based on the question in your comment, there are code injection vulnerabilities. Add the System reference and namespace as shown right above, then replace the str with:
string str =
#" a=1, oops = (new Func<int>(() => {
Console.WriteLine(
""Security incident!!! User {0}\\{1} exposed "",
Environment.UserDomainName,
Environment.UserName);
return 1;
})).Invoke() ";
The question you described is something like deserialization, that is, contructing objects from data form(like string, byte array, stream, etc). Hope this link helps: http://msdn.microsoft.com/en-us/library/vstudio/ms233843.aspx
Here's a solution using ExpandoObject to store it after parsing it yourself. Right now it adds all values as strings, but you could add some parsing to try to turn it into a double, int, or long (you'd probably want to try it in that order).
static dynamic Parse(string str)
{
IDictionary<String, Object> obj = new ExpandoObject();
foreach (var assignment in str.Split(','))
{
var sections = assignment.Split('=');
obj.Add(sections[0], sections[1]);
}
return obj;
}
Use it like:
dynamic d = Parse("a=1,b=2,c=3");
// d.a is "1"
I have the following problem, I want to parse a Json object I get passed by a url query string
e.g.
...&json={tags=[tag1,tag2]}
I have used
JsonConvert.DeserializeObject<Dictionary<string, object>>(json)
But when calling the Deserialize method I get an error
Newtonsoft.Json.JsonReaderException : Unexpected character encountered while parsing value: d. Line 1, position 8.
If I pass in the string
"{tags:[\"tag1\",\"tag2\"]}
It works fine, I don't want my users to have to add the "" quotes
Is there a way to work around this problem?
pseudocode For a solution could be...
Grab the json query string element.
Split on first equals "=".
Grab all text between "{tags=[" and "]}"
Take that text split on ","
trim any whitespace off of the items.
Join them back together but put quotes around them and coma delimited them.
put that value back inbetween "{tags=[" and "]}" ie "{tags=[" + newValue+ "]}"
Here is some sample C# code...
[Test]
public void TestHack()
{
string almost = "{tags=[tag1,tag2]}";
string json = this.HackToJson(almost);
Trace.WriteLine(json);
}
public string HackToJson(string almostJson)
{
if( almostJson.StartsWith("{tags=[") && almostJson.EndsWith("]}"))
{
int tagsLen = "{tags=[".Length;
string tags = almostJson.Substring(tagsLen, almostJson.Length - (tagsLen + 2));
var items = tags.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var itemsCleaned = (from c in items select "\"" + c.Trim() + "\"");
var jsonpart = string.Join(",", itemsCleaned);
var json = string.Format("{{tags=[{0}]}}", jsonpart);
return json;
}
throw new NotImplementedException("not sure what to do here... ");
}
I'm looking for a way to clean up the following json string in C# to be more usable.
"?{\"token\":\"I3dt-MIByyWD5-XqF6VT3hQSk8qvy9r6\"}"
basically just for a way to strip it down to
"token:I3dt-MIByyWD5-XqF6VT3hQSk8qvy9r6" or just "I3dt-MIByyWD5-XqF6VT3hQSk8qvy9r6"
I assume that a would be good for accomplishing this but unfortunately i've never written one before and a bit lost on how to get what im looking for using one. The parsing is happening in C# BTW.
EDIT: Correction a regular expression probably wont do what i want... i want to format the string.. not just validate it.
It is better to parse it into a JSON object, then using the JSON API, to get the value of the token key from there.
Check this out:
http://msdn.microsoft.com/en-us/library/bb299886.aspx
there is a class, called JsonTextReader, which you can use for parsing.
Here's how:
string jsonText = #"[""Europe"", ""Asia"", ""Australia"", ""Antarctica"",
""North America"", ""South America"", ""Africa""]";
using (JsonTextReader reader = new JsonTextReader(new
StringReader(jsonText)))
{
while (reader.Read())
{
if (reader.TokenClass == JsonTokenClass.String &&
reader.Text.StartsWith("A"))
{
Console.WriteLine(reader.Text);
}
}
}
you can try a method like this. the & take it for separator if you have a chain of such "?{\"token\":\"I3dt-MIByyWD5-XqF6VT3hQSk8qvy9r6\"&\"other\":\"123\"}". Also clears the characters "and \
static string MyParserJson(string sjson, string key)
{
try
{
if (!(sjson.Contains("{") && sjson.Contains("}")))
throw new ApplicationException("don't exist { or }");
int inipos = sjson.IndexOf("{");
int endpos = sjson.IndexOf("}");
var myjson = sjson.Substring(inipos + "{".Length, endpos - (inipos + "{".Length));
string[] ajson = myjson.Split('&');
foreach (var keyval in ajson)
{
if (!keyval.Contains(":"))
continue;
string[] afind = keyval.Split(':');
if (afind[0].Contains(key))
{
return afind[1].Replace("\"", "").Replace("\\", "").Trim();
}
}
}
catch
{
//test
}
return string.Empty;
}
var uri = "?{\"token\":\"I3dt-MIByyWD5-XqF6VT3hQSk8qvy9r6\"}";
var token = MyParserJson(uri, "token");