I'm currently trying to tackle a situation where we have invalid Json that we are trying to deserialize. The clinch point is we're supplied Json where property assignment is declared with an = instead of a : character.
Example Json:
{
"Field1" = "Hello",
"Field2" = "Stuff",
"Field3" = "I am non-Json Json, fear me",
"Field4" = 8
}
Has anyone had any luck using Json.Net to deserialize this into an object of relating structure into C# where = is in use instead of :
I've been trying to write a JsonConverter to read past the = but it always complains it's got an = instead of a : and throws an exception with the message "Expected ':' but got: =. Path ''".
I don't see any way past this except for writing my own deserialization process and not using the Json.Net library. which sucks for something so close to being valid Json (But I suppose is fair enough as it is invalid)
When reader.ReadAsString(); is hit it should read Field1 out but obviously it hasn't met its friend the : yet and so proceeds to fall over saying "what the hell is this doing here?!". I've not got any JsonConverter implementation examples because there's really not much to show. just me attempting to use any of the "Read..." methods and failing to do so.
If property assignment is declared with an = instead of a : character then it is not JSON.
If you don't expect any = in the values of the object then you can do a
string json = invalidData.Replace("=", ":");
and then try to parse it.
As mentioned by #Icepickle, there are risks involved in doing this.
My answer works as a quick fix/workaround, but you will eventually need to make sure that the data you are receiving is valid JSON.
There is no point in trying to deserialize invalid JSON.
As suggested by others, the easiest way to get around this issue is to use a simple string replace to change = characters to : within the JSON string prior to parsing it. Of course, if you have any data values that have = characters in them, they will be mangled by the replacement as well.
If you are worried that the data will have = characters in it, you could take this a step further and use Regex to do the replacement. For example, the following Regex will only replace = characters that immediately follow a quoted property name:
string validJson = Regex.Replace(invalidJson, #"(""[^""]+"")\s?=\s?", "$1 : ");
Fiddle: https://dotnetfiddle.net/yvydi2
Another possible solution is to alter the Json.Net source code to allow an = where a : normally appears in valid JSON. This is probably the safest option in terms of parsing, but requires a little more effort. If you want to go this route, download the latest source code from GitHub, and open the solution in Visual Studio 2015. Locate the JsonTextReader class in the root of the project. Inside this class is a private method called ParseProperty. Near the end of the method is some code which looks like this:
if (_chars[_charPos] != ':')
{
throw JsonReaderException.Create(this, "Invalid character after parsing property name. Expected ':' but got: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
}
If you change the above if statement to this:
if (_chars[_charPos] != ':' && _chars[_charPos] != '=')
then the reader will allow both : and = characters as separators between property names and values. Save the change, rebuild the library, and you should be able to use it on your "special" JSON.
Related
I have a string in plain text which contains brackets like JSON format as it is created using JavaScriptSerializer().Serialize() method. I need to remove brackets and collon and want to convert it into key = value, key = value format.
Need to convert
{
"account":"rf750",
"type":null,
"amount":"31",
"auth_type":"5",
"balance":"2.95",
"card":"re0724"
}
to
'account=rf750,type=null,amount=31,authe=5,balanc=2.95,card=re0724'
Well, you've got three different things going on here.
The first, and surface issue, is: how do you change the string?
Simple - you do some string substitutions, preferably using Regex. Remove the starting/ending braces, change [a]:"[b]", to [a]=[b], - or however you want the final format to look like.
The second, and slightly deeper issue is: JSON isn't just a simple list of keys=values. You can have nesting. You can have non-string data. Simply saying you want to change the JSON result to key=value,key=value,key=value, etc - is fragile. How do you know the JSON structure will be what you're expecting? JSON Serialization will serialize successfully even if you've got nested structures, non string/int data, etc. And if you want solid code that doesn't easily break, you have to figure out: how do I handle this? Can I handle this?
The third, and final thing is: you're taking a standard data format schema and figuring out how to translate it to a nonstandard data format. 90% of the time someone does that, they deserve to be shot. Seriously, spend some solid time asking yourself whether you can use the JSON as-is, and whether the process wanting key=value,key=value,etc can be changed to use an actual standardized data format.
Here is simple solution which (1) parses json to Dictionary and (2) uses String.Join and Linq Select to provide desired output:
using System.Linq;
using Newtonsoft.Json;
..
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
var str = string.Join(',', dict.Select(r => $"{r.Key}={r.Value}"));
str-variable now contains:
account=rf750,type=,amount=31,auth_type=5,balance=2.95,card=re0724
Well thanks everyone for your time and response. your answer led me towards solution and finally i found the following solution which resolved the issue perfectly.
var jObj = (JObject)JsonConvert.DeserializeObject(modelString);
modelString = String.Join("&",jObj.Children().Cast<JProperty>().Select(jp => jp.Name + "="+ HttpUtility.UrlEncode(jp.Value.ToString())));
the above code converts the JSON into a url encoded string and remove the JSON format
I'm somehow having troubles deserializing a json string into a simple List or string[] (I don't care which).
As of what I know, this is how to do this job:
JsonConvert.DeserializeObject<List<string>>(jsonString);
Here I am getting a RuntimeBinderException. It complains about the parameter, although my json string is valid and simple: a:1:{i:0;s:10:"Sahibinden";}
What you have isn't JSON is a serialized PHP object. There have been some tools that work well with this in C# but there isn't native support. If you own the PHP, then convert the object/array to JSON first. If not try the information on this question: https://stackoverflow.com/a/1923626/474702
Your JSON is invalid. Problems:
a:1 should be inside an object bracket of {}
The : before the { is invalid, you need a , there
The ; just after i:0 is invalid, you need a comma there
You repeat the mistake described in 1. and 2. inside your {} brackets as well
Solution: You need to read about JSON and make sure you understand its syntax.
What would be the simplest way of parsing this string I just want to get the two values out of it. I need to get the value after QueryParameter Parameter=\ and then the value from after \"$MPElement[Name='
Any help apreciated I did try the following code
string myString = listQueryParameter[0]._parameter.ToString();
string text= myString.Split(new [] {"QueryParameter Parameter="}, StringSplitOptions.None)[1];
But it still gave me everything after value along with it thanks.
<QueryParameter Parameter=\"TypeProjectionId\" Value=\"$MPElement[Name='System.WorkItem.Incident.View.ProjectionType']$\" xmlns=\"clr-namespace:Microsoft.EnterpriseManagement.UI.ViewFramework;assembly=Microsoft.EnterpriseManagement.UI.ViewFramework\" />"
Your input looks like XML, but isn’t really valid XML.
My recommendation is to investigate where this stuff comes from, and fix the source so that it will produce correct XML. My guess is that in actuality you already have valid XML, but you looked at the string in the VS debugger and saw it with the backslashes added and then assumed that they are part of the string. If this is the case, then rest assured that they are not.
For reference, valid XML might look like this:
<QueryParameter Parameter="TypeProjectionId" Value="$MPElement[Name='System.WorkItem.Incident.View.ProjectionType']$" xmlns="clr-namespace:Microsoft.EnterpriseManagement.UI.ViewFramework;assembly=Microsoft.EnterpriseManagement.UI.ViewFramework" />
In other words, it’s the same as yours but without the backslashes.
Now we can use XElement.Parse to turn this into a parsed value:
var xml = XElement.Parse(myString);
If you feed the invalid XML to this, this will throw.
Now we want to look at the values of the two attributes Parameter and Value:
var parameter = xml.Attribute("Parameter").Value;
var value = xml.Attribute("Value").Value;
At this point, value contains the string $MPElement[Name='System.WorkItem.Incident.View.ProjectionType']$. You said you wanted the part after Name=, so let’s use a regular expression for that:
var match = Regex.Match(value, #"\bName='([^']*?)'");
if (!match.Success)
throw new Exception("The Value attribute is not in a recognized format.");
var innerValue = match.Groups[1].Value;
I'm using the ExportAPI from MailChimp. It sends back a "root"-less Json string like so:
["Email Address", "First Name", "Last Name"]
["jeff#mydomain.com", "Jeff", "Johnson"]
["tubbs#mydomain.com", "Tubbs", "McGraw"]
No brackets, nothing- just a couple of arrays. Loading it into a JArray only picks up the first object:
JArray jsonArray = new JArray.Parse(jsonResponse);
Console.WriteLine(jsonArray);
//Outputs:
//Email Address
//First Name
//Last Name
I'm hoping to copy the contents of the string into a database and need to access the response with LINQ. Any suggestions as to the correct way to work with a Json Object like I've shown above (using Json.net or otherwise?)
Pad the string with a root element, just add '[' and ']'?
This behavior is actually completely on purpose as mentioned in the docs. The reasoning is that a full dump of a list's data can easily be way too large to consistently fit it in memory and parse it. As such, and given the return format, you're expected to use a newline as the delimiter (or read it off the wire that way), parse each object individually, and then do whatever you need with them.
I am not familiar with doing that in C#/Linq, but the PHP example on the docs page does exactly that.
I am using the excellent Json.Net library to serialize my entities generated by entity framework. I use the following code to do so :
using (MyVoucherEntities context = new MyVoucherEntities())
{
List<MyObject> list = context.MyObjects.ToList();
string json = JsonConvert.SerializeObject(list);
}
Everything goes well I mean, the objects are correctly serialized except one think : it adds escape characters "\" that makes me having nightmare when deserializing on the client side.
[
{
\"$id\": \"1\",
\"CreationDate\": \"\\\/Date(1293186324257+0000)\\\/\",
\"ImageUrl\": \"http:\/\/www.google.com\",
\"Title\": \"Here is a title\"
} ]
Does anybody know why and how I can get rid of these escape characters slash "\" ?
I suspect it's not actually adding escape characters at all. I suspect you're just looking at the string in a debugger, and that's adding the escaping.
Try dumping it to a file or the console.
I found the reason why I had escape characters in my string ("\"). After serializing my objects, I am returning the JSON string to the client app through a WCF. Apparently, WCF is automatically adding these characters to the string before sending it to the network. It is a default behaviour and is apparently mandatory.
As I didn't want these escape characters, the workaround is to change the return type of the service to Stream and so, returning your JSON string inside a memory stream. It works perfectly and is quite fast.
It's invalid JSON because the result of serializing a list of objects is an array, i.e., the json will start with a [ and ending with a ]. To fix this, you need to wrap the list of objects in a root object (any instance of a class or an anonymous object), so, the resulting string will start with a { and end with }.
For example:
var output = new List<object>();
var json = JsonConvert.SerializeObject(new { root = output }, Formatting.Indented);
Response.Write(json);
Does this one help? I used it in my WebService to return Json content:
private HttpContent ConvertToJsonContent(object content)
{
string jsonObject = JsonConvert.SerializeObject(content, Newtonsoft.Json.Formatting.Indented);
return new StringContent(jsonObject, Encoding.UTF8, "application/json");
}
If strings have a "\" the two "\\" will come back. You can avoid this by using Unescape
private HttpContent ConvertToJsonContent(object content)
{
string jsonObject = Regex.Unescape(JsonConvert.SerializeObject(content, Newtonsoft.Json.Formatting.Indented));
return new StringContent(jsonObject, Encoding.UTF8, "application/json");
}
I should note that you have not completely quoted the outputted stuff (I got the url to work in your answer - that should have been edited into your question rather than put as an answer). The string I got back in a file was this:
"[{\"$id\":\"1\",\"CreationDate\":\"\\\/Date(1293186324257+0000)\\\/\",\"ImageUrl\":\"http:\/\/www.c-tina.com\/MyVoucherAdmin\/Images\/shop22\/burger.jpg\",\"Title\":\"Get one burger for free\",\"Description\":\"Bla lbzlfpzkfgmzke\\rdmjdgmj\\r\\r\\rlgfpzkegmkzepk\",\"ShopId\":22,\"PromotionId\":15,\"Shop\":null,\"Features\":[],\"SingleStats\":[],\"WhatsHots\":[],\"EntityKey\":{\"$id\":\"2\",\"EntitySetName\":\"Promotions\",\"EntityContainerName\":\"MyVoucherEntities\",\"EntityKeyValues\":[{\"Key\":\"PromotionId\",\"Type\":\"System.Int32\",\"Value\":\"15\"}]}}]"
the key thing to me is that there are unescaped quotes at the front and end which makes me think that whatever is outputting it is deciding it needs to be quoted and if you are surrounding it in quotes you ahve to escape the quotes that are inside it.
Without seeing the full output its hard to say if the problem is in teh code you've quoted above to generate the JSON or if there is a problem at a later step of processing this which is causing the quoting. Have you debugged and confirmed that the output of your serialize call is definitely producing the escaped version rather than it being done at a later stage potentially? If you're not used to the debugger then pay attention to Jon Skeet's suggest of dumping it to file or console to make sure there is no confusion that way.