Does C# have API that removes escaped JSON string? - c#

I have a program where I receive JSON from a server of the format:
{
"Parent1Key":"{\n \"Child11Key\" : 0,\n \"Child21Key\" : \"successfully.\"\n}\n",
"Parent2Key":"{\n \"child21\" : true,\n \"Child22\" : \"successful.\"\n}\n"
}
This string is manually escaped in our program to be of the format:
{"Parent1Key":{ "Child11Key" : 0, "Child21Key" : "successfully." },"Parent2Key":{ "child21" : true, "Child22" : "successful." }}
Sorry, the specific code to make this change cannot be shared in this question.
so that we can pass it to our deserialize logic.
We are getting problem when we save strings with escaped characters like when "child22" : "{text", or "child22" : "text}".
Is there a C# API that removes the escaped JSON formatting correctly and returns the required string.

So it seems like you have some JSON which has been constructed by serializing some objects (Parent1Key and Parent2Key), then taking those serialized strings, adding them to another object and serializing that. So the inner objects end up double-serialized.
What you need to do is reverse that process by re-parsing the inner objects. You can do that using Json.Net:
JObject obj = JObject.Parse(json);
obj["Parent1Key"] = JObject.Parse((string)obj["Parent1Key"]);
obj["Parent2Key"] = JObject.Parse((string)obj["Parent2Key"]);
json = obj.ToString();
Fiddle: https://dotnetfiddle.net/z2zpd5

Related

Append data in a json file in C#

How would i keep appending data?
I have this:
{
"13232": [
"2012952"
]
}
And i want to add an another object to it, example:
{
"13232": [
"2012952"
],
"19213": [
"2016086"
]
}
This is the code i use:
JArray array = new JArray();
array.Add(Itemid);
JObject o = new JObject();
o[Userid] = array;
string json = o.ToString(Formatting.Indented);
//i know this keeps appending text but how would i append it inside the { and }?
File.AppendAllText("E:/media.json", json);
I literally have no idea how to keep adding it, but maybe someone else has?
You won't be able to use file append operations to do this. File append operations can only add text to the end, they can't insert text at some point in the middle. This makes it impossible to use file-append to keep the JSON valid.
You have two choices that I can think of:
Read the entire file into an object, add your object, and then
rewrite the entire file (poor performance)
Open the file read/write, parse through
until you get to the closing curly brace, then write the remaining
data, then write the close curly brace (not trivial)
The safest approach is read-update-rewrite (applies to JSON and XML format as they don't support appending).
Next option if you can live with invalid JSON is to simply concatenate JSON fragments with code you have and than use SupportMultipleContent in JsonReader to read fragments Read Multiple Fragments With JsonReader
If those approaches don't work and your format is fixed - find position of last ] in the file, seek stream there and write new array elements and append ]}.
I recommand you use Newtonsoft Json lib, available as a nuget package.
You can the make a model class to represent on of the json node then you can de-serialize you Json to that model and build an array containing the new element at the end to then re-serialize it to json after.
Look at this MSDN page about it: https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx
Edit: Actual NewtonSoft Documentation
In steps: 1 Deserialize the collection
2: And a new class instance with listName.Add(className);
3: Reserialize the collection
My approach was to add an additional step to my string handling.
public void WriteObjectToFile(object objectToInsert)
{
var stringToSaveToFile = JsonConvert.SerializeObject(objectToInsert) + ",";
File.AppendAllText(this.path, stringToSaveToFile);
}
public List<objects> GetListFromFile()
{
var notQuiteJSONstring = File.ReadAllTest(this.path);
var treatment1 = notQuiteJSONstring.Substring(0, notQuiteJSONstring.Length -1); //remove the trailing comma
var treatment2 = "[" + treatment1 + "]"; // wrap string with brackets to deserialize as list
var list = JsonConvert.DeserializeObject<List<object>>(treatment2);
return list;
}

Can't parse json from Resources

In resources I have json file with next content:
{
"EU": [
"Germany",
"Ukraine",
"United Kingdom",
"Hungary"
]
}
I want to deserialize it into Dictionary<string,List<string>>
I've tried next :
var json = Encoding.UTF8.GetString(Resources.regionGroups);//Resources.regionGroups return byte[]
return JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(json);
But every time I get exception as variable json is in incorect json format.
What can cause this? I've tried the same deserialization but with jsonString as hard-coded and it works.
Detailed exception message :
Unexpected character encountered while parsing value: . Path '', line
0, position 0.
UPDATE :
After removing all spaces
var json = Regex.Replace(Encoding.UTF8.GetString(Resources.regionGroups), "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1");
from string I have next one
"{\"EU\":[\"Germany\",\"Ukraine\",\"United Kingdom\",\"Hungary\"]}"
which also reproduce exception.
Well #AmitKumarGhosh was right about encoding, as I think.
So I've tried to change type of my json file in the Resources. I've changed it from binary to text file and this helps.
So parsing now is very simple :
JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(Resources.regionGroups);

Why is this Json.Net conversion from XML and JSON not working?

You can enter either of these URLs into a browser and verify that they return valid xml:
http://maps.googleapis.com/maps/api/geocode/xml?`address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false"
...or json:
http://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false%22
...but when attempting to get the xml programmatically using this code (after installing Json.NET via NuGet into my project and dropping a dataGridView on my Windows form):
dataGridView1.DataSource = GetLocationData("http://maps.googleapis.com/maps/api/geocode/xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false");
private JArray GetLocationData(string uri)
{
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
var webResponse = (HttpWebResponse)webRequest.GetResponse();
var reader = new StreamReader(webResponse.GetResponseStream());
string s = reader.ReadToEnd();
return JsonConvert.DeserializeObject<JArray>(s);
}
...I get:
Newtonsoft.Json.JsonReaderException was unhandled
_message=Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
I thought, okay, this actually is json code, not xml, so I replaced "xml" with "json" in the URL, expecting more joy in Mudville.
However, when attempting to get the same data as json, I also get an exception, namely, "System.InvalidCastException was unhandled _message=Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'Newtonsoft.Json.Linq.JArray'."
Why, and how can I fix it? Is it possible to also grab the data as xml?
Using the json URL is correct. Your problem is that the JSON response is not giving you an array which is your error.
Notice that the response you get back is an object denoted by the {
{
"results" : [
{
"address_components" : [
{
"long_name" : "1600",
"short_name" : "1600",
"types" : [ "street_number" ]
},
....
If it was an array, you would get back [ instead. You should use JObject or a custom model instead of JArray. The results element is what contains the actual array that you will need to loop through.
Pseudo for the result you are actually getting in the response:
object
{
Result[] results;
string status;
}
You can also grab the XML version if you want, but then you need to actually have an object model defined to match and use the XmlSerializer to deserialize it or load it into an XmlDocument (lots of ways to work with XML). However, you cannot pass XML into the JSON serializer as it is expecting a JSON string.
EDIT:
There are methods on JsonConvert to convert from XML. See this answer here: How to convert JSON to XML or XML to JSON?

Json.NET, can SerializeXmlNode be extended to detect numbers?

I am converting from XML to JSON using SerializeXmlNode. Looks the expected behavior is to convert all XML values to strings, but I'd like to emit true numeric values where appropriate.
// Input: <Type>1</Type>
string json = JsonConvert.SerializeXmlNode(node, Newtonsoft.Json.Formatting.Indented, true);
// Output: "Type": "1"
// Desired: "Type": 1
Do I need to write a custom converter to do this, or is there a way to hook into the serialization process at the appropriate points, through delegates perhaps? Or, must I write my own custom JsonConverter class to manage the transition?
Regex Hack
Given the complexity of a proper solution, here is another (which I'm not entirely proud of, but it works...).
// Convert to JSON, and remove quotes around numbers
string json = JsonConvert.SerializeXmlNode(node, Newtonsoft.Json.Formatting.Indented, true);
// HACK to force integers as numbers, not strings.
Regex rgx = new Regex("\"(\\d+)\"");
json = rgx.Replace(json, "$1");
XML does not have a way to differentiate primitive types like JSON does. Therefore, when converting XML directly to JSON, Json.Net does not know what types the values should be, short of guessing. If it always assumed that values consisting only of digits were ordinal numbers, then things like postal codes and phone numbers with leading zeros would get mangled in the conversion. It is not surprising, then, that Json.Net takes the safe road and treats all values as string.
One way to work around this issue is to deserialize your XML to an intermediate object, then serialize that to JSON. Since the intermediate object has strongly typed properties, Json.Net knows what to output. Here is an example:
class Program
{
static void Main(string[] args)
{
string xml = #"<root><ordinal>1</ordinal><postal>02345</postal></root>";
XmlSerializer xs = new XmlSerializer(typeof(Intermediary));
using (TextReader reader = new StringReader(xml))
{
Intermediary obj = (Intermediary)xs.Deserialize(reader);
string json = JsonConvert.SerializeObject(obj , Formatting.Indented);
Console.WriteLine(json);
}
}
}
[XmlRoot("root")]
public class Intermediary
{
public int ordinal { get; set; }
public string postal { get; set; }
}
Output of the above:
{
"ordinal": 1,
"postal": "02345"
}
To make a more generic solution, yes, you'd have to write your own converter. In fact, the XML-to-JSON conversion that takes place when calling SerializeXmlNode is done using an XmlNodeConverter that ships with Json.Net. This converter itself does not appear to be very extensible, but you could always use its source code as a starting point to creating your own.

Regex to replace JSON structure

I have JSON text like this :
...
"simples":{
"AS100ELABQVKANID-91057":{
"meta":{
"sku":"AS100ELABQVKANID-91057",
"price":"3669000.00",
"original_price":"3379000.00",
"special_to_date":"2015-03-19 23:59:59",
"shipment_type":"1",
"special_price":"3299000.00",
"tax_percent":"10.00",
"sourceability":"Sourceable",
"quantity":"15",
"variation":"...",
"package_type_position":"0",
"min_delivery_time":"1",
"max_delivery_time":"3",
"attribute_set_name":"electronics",
"3hours_shipment_available":false,
"estimated_delivery":"",
"estimated_delivery_position":""
},
"attributes":{
"package_type":"Parcel"
}
}
},
"description":
...
The above text appears repeatedly in my JSON text. I am trying to build every result to this :
"simples":[],"description"
So far, I have made this regex :
\"simples\":{(?:.*v(?:|=)|(?:.*)?)},\"description\"
But the result is cut everything from my first "simples" into last "description".
Regex newbie here.
Thanks in advance
I recommend parsing the JSON, replacing the value, then re-stringifying it
var obj = JSON.parse(json);
obj.simples = [];
json = JSON.stringify(obj);
Using a regexp for this is pure insanity
Don't use Regex to parse JSON; use a JSON parser.
Here is how you can do this using JSON.Net, assuming the object containing simples is part of a flat list of results:
JArray array = JArray.Parse(json);
foreach (JObject obj in array)
{
obj["simples"].Parent.Remove();
}
json = array.ToString();
If your JSON is more complicated (i.e. "simples" can appear at more than one level in the JSON), then you will need a recursive search to find and remove it. This answer has a helper method that can find a specific property by name anywhere in the JSON and return a list of all occurrences. Once you have the list of occurrences, you can then loop through them and remove them as shown above.

Categories

Resources