I get an answer from the server in the form of such JSON:
var zohozoho_atliview92 = {\"Itinerary\":[
{\"Client_Email\":\"garymc\",
\"Client_Name\":\"Gary\",
\"NT_Number\":\"NT-1237\",\"Number_of_Nights\":7,
\"ID\":\"24297940\",
\"Itinerary_Name\":\"Icelandnights\",
\"Tour_Template_Name\":\"Iceland FireDrive\",
\"Departure_Date\":\"2018-07-04\"}
]};
I need to remove this: var zohozoho_atliview92 = {\"Itinerary\":[ and delete last 3 characters ]}; to Deserialize it in my object.
How can i make it using Regular Expressions? Or is there a better variant?
is there a better variant?
Yes you can parse your json escaped string to JObject.
And then you can access any key/value pair from json with Querying JSON with LINQ
Or you can map your JObject to your custom type by using var result = jObject.ToObject<T>();
class Program
{
static void Main(string[] args)
{
var zohozoho_atliview92 = "{\"Itinerary\":[ {\"Client_Email\":\"garymc\", \"Client_Name\":\"Gary\", \"NT_Number\":\"NT-1237\",\"Number_of_Nights\":7, \"ID\":\"24297940\", \"Itinerary_Name\":\"Icelandnights\", \"Tour_Template_Name\":\"Iceland FireDrive\", \"Departure_Date\":\"2018-07-04\"}]}";
JObject jObject = JObject.Parse(zohozoho_atliview92);
Console.WriteLine(jObject);
Console.ReadLine();
}
}
Output:
This is not JSON, it's Javascript (wich object declaration is JSON).
Regular expressions are slow, I would advise you to use Substring
var start=inputString.IndexOf("[");
var end=("]");
var json=inputString.Substring(start, end-start);
There might be some of by one errors, test and correct.
It would be even faster but weaker to hardcode start.
Please help.
I have a text from html, and I need to parse it.
Text:
converter.rates =
{"3":{"USD":{"buy":27.950001,"sell":28.190001},"EUR":{"buy":32.049999,"sell":32.689999}},"8":{"RUB":{"buy":0.27,"sell":0.43},"USD":{"buy":27.799999,"sell":28.200001},"EUR":{"buy":31.700001,"sell":32.549999}},"41":{"USD":{"buy":28.0,"sell":28.200001},"EUR":{"buy":31.950001,"sell":32.650002}},"46":{"RUB":{"buy":0.413,"sell":0.443},"USD":{"buy":28.0,"sell":28.25},"EUR":{"buy":31.73,"sell":32.73}},"47":{"RUB":{"buy":0.41,"sell":0.448},"USD":{"buy":27.98,"sell":28.15},"EUR":{"buy":31.889999,"sell":32.540001}},"48":{"RUB":{"buy":0.4,"sell":0.43},"USD":{"buy":28.0,"sell":28.200001},"EUR":{"buy":32.099998,"sell":32.490002}},"52":{"RUB":{"buy":0.41,"sell":0.43},"USD":{"buy":27.950001,"sell":28.25},"EUR":{"buy":32.0,"sell":32.5}},"77":{"RUB":{"buy":0.38,"sell":0.43},"USD":{"buy":28.049999,"sell":28.200001},"EUR":{"buy":32.049999,"sell":32.5}},"79":{"RUB":{"buy":0.412,"sell":0.444},"USD":{"buy":27.950001,"sell":28.799999},"EUR":{"buy":31.959999,"sell":33.099998}},"80":{"RUB":{"buy":0.38,"sell":0.43},"USD":{"buy":28.030001,"sell":28.190001},"EUR":{"buy":32.0,"sell":32.450001}},"70":{"RUB":{"buy":0.39,"sell":0.42},"USD":{"buy":28.0,"sell":28.25},"EUR":{"buy":32.0,"sell":32.200001}},"1":{"RUB":{"buy":0.42658,"sell":0.42658},"USD":{"buy":28.036648,"sell":28.036648},"EUR":{"buy":32.256161,"sell":32.256161}},"4":{"RUB":{"buy":0.42,"sell":0.43},"USD":{"buy":27.950001,"sell":28.25},"EUR":{"buy":32.150002,"sell":32.599998}},"10":{"RUB":{"buy":0.414,"sell":0.435},"USD":{"buy":28.0,"sell":28.200001},"EUR":{"buy":32.0,"sell":32.599998}},"13":{"RUB":{"buy":0.275,"sell":0.46},"USD":{"buy":27.9,"sell":28.200001},"EUR":{"buy":31.67,"sell":32.599998}},"15":{"RUB":{"buy":0.3749,"sell":0.4395},"USD":{"buy":27.985001,"sell":28.2075},"EUR":{"buy":32.036366,"sell":32.529091}},"31":{"RUB":{"buy":0.275,"sell":0.42},"USD":{"buy":27.9,"sell":28.139999},"EUR":{"buy":31.799999,"sell":32.400002}},"32":{"RUB":{"buy":0.42,"sell":0.5},"USD":{"buy":28.07,"sell":28.299999},"EUR":{"buy":32.150002,"sell":32.599998}},"39":{"USD":{"buy":28.07,"sell":28.25},"EUR":{"buy":32.150002,"sell":32.549999}},"40":{"RUB":{"buy":0.41,"sell":0.43},"USD":{"buy":27.950001,"sell":28.139999},"EUR":{"buy":32.049999,"sell":32.400002}},"64":{"RUB":{"buy":0.4,"sell":0.425},"USD":{"buy":27.9,"sell":28.200001},"EUR":{"buy":32.099998,"sell":32.599998}},"73":{"RUB":{"buy":0.4,"sell":0.43},"USD":{"buy":28.0,"sell":28.299999},"EUR":{"buy":32.0,"sell":32.549999}},"74":{"RUB":{"buy":0.41,"sell":0.435},"USD":{"buy":28.049999,"sell":28.25},"EUR":{"buy":31.799999,"sell":32.5}},"85":{"RUB":{"buy":0.3,"sell":0.43},"USD":{"buy":28.0,"sell":28.200001},"EUR":{"buy":32.099998,"sell":32.52}},"86":{"RUB":{"buy":0.37,"sell":0.42},"USD":{"buy":28.0,"sell":28.200001},"EUR":{"buy":32.0,"sell":32.799999}},"88":{"RUB":{"buy":0.35,"sell":0.5},"USD":{"buy":28.0,"sell":28.15},"EUR":{"buy":32.099998,"sell":32.450001}},"90":{"RUB":{"buy":4.0,"sell":4.4},"USD":{"buy":28.0,"sell":28.15},"EUR":{"buy":31.950001,"sell":32.450001}}}
I need next info from it:
code of bank - "3"
and USD rate - 27.950001, 28.190001
My expression:
#"(\d+)":..USD....\w+..(\d+.\d+)........(\d+.\d+)"
But it didn't work, because the USD does not always go first after the bank code
This is a JSON document. JSON is a recursive format, and regular expressions are notoriously hard to use when parsing recursive data.
Please use a specified parser, like NewtonSoft JSON:
var rawData = #"converter.rates = { ... }"; // original string
var rawJson = rawData.Substring("converter.rates = ".Length); // remove the prefix
var json = JObject.Parse(rawJson); // convert to a JSON data structure
Then you can use it like a dictionary:
foreach(var codeEntry in json)
{
foreach(var currencyEntry in codeEntry.Value)
{
var code = codeEntry.Key;
var currency = currencyEntry.Key;
var buy = currencyEntry.Value["buy"].Value<double>();
var sell = currencyEntry.Value["buy"].Value<double>();
Console.WriteLine($"code of bank - {code} and {currency} rate - {buy}, {sell} ");
}
}
If you still want to use regex, this can do it:
#"""(?<code>\d+)"":\{.*?(?<=""USD""):\{""buy"":(?<buy>\d+\.\d+),""sell"":(?<sell>\d+.\d+)\}"
It is build from your example. Basically it creates three named Groups 'code', 'buy' and 'sell'. Other than that it matches literal characters, only using a look behind '(?<=""USD"")' to find 'USD' to get the wanted rates.
Edit:
If you have a html document and want to grap the 'converter.rates' var as text, you can use this regex:
#"converter.rates\s?=.*\}\}\}"
It looks for the 3 '}' ending the string.
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;
}
How can I read such outputs in C# perhaps converting to C# native lists?
Without parse the text and split and make string manipulations, must have an easy way
[
"\/recordings\/series\/seasons\/432250",
"\/recordings\/series\/seasons\/263560"
]
I'm interested in just the numbers, I know that I could easily just use a string split using ',' and get the last 6 numerics chars
another example:
[
"\/recordings\/series\/episodes\/428389",
"\/recordings\/series\/episodes\/428386",
"\/recordings\/movies\/airings\/434062",
"\/recordings\/series\/episodes\/430801"
]
In that case will be interesting to know the <> paths
typical json that I'm using to deserialize doesn't work with those dictionary likes json strings
thanks
Many people like to use the Json.NET / Newtonsoft.Json library. You can easily add it as a NuGet package to your project and then use it like this:
var json = "[\"/recordings/series/seasons/432250\",\"/recordings/series/seasons/263560\"]";
var list = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(json);
For the numbers, there are lots of ways to go about it. Here's one of many:
var numbersList = list.Select(x => x.Split('/').Last()).ToList();
Try code below.
var json = #"[
""\/recordings\/series\/episodes\/428389"",
""\/recordings\/series\/episodes\/428386"",
""\/recordings\/movies\/airings\/434062"",
""\/recordings\/series\/episodes\/430801""
]";
var jarray = JArray.Parse(json);
var list = from a in jarray
let val = a.Value<string>()
let rgroup = Regex.Match(val, #"[^0-9]*([0-9]+)")
let vstring = rgroup.Groups[1]
select int.Parse(vstring.Value);
It requires Newtonsoft.Json library, and list has type of IEnumerable<int>. And also don't forget to add
using System;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
To the top of your .cs file.
A simple way is to use JavaScriptSerializer from System.Web.Extensions.dll. Its Deserialize<T>() method lets you specify the type that the JSON should be deserialized to. In the case of simple primitives, such as an array of strings, it works magically without any fuss. An example:
var json = "[\"\\/recordings\\/series\\/seasons\\/432250\",\"\\/recordings\\/series\\/seasons\\/263560\"]";
var stringArray = new JavaScriptSerializer().Deserialize<string[]>(json);
foreach (var element in stringArray)
Console.WriteLine(element.Split('/').Last());
I want to avoid importing a huge library to gain full JSON support.
My use case is REALLY simple: I need a parser to handle one specific case of JSON, where both key and value are strings, ie. { "name": "David" }. No nesting, no arrays, no object serialization.
The reason being, I use JSON only for i18n, and I have structure my translation files to be flat JSON.
Is it a good idea to hand roll my own parser?
Is there one out there already?
Are there easier solutions to my problem?
EDIT: yes, I do know JSON.net is the defacto solution for .NET, but it's not the solution for Unity (not natively). I really only need a tiny portion of its power.
System.Json might do the trick for you.
The JsonValue.Parse() Method parses JSON text and returns a JsonValue like
JsonValue value = JsonValue.Parse(#"{ ""name"": ""David"" }");
You can also have a look at The JavaScriptSerializer class is used internally by the asynchronous communication layer to serialize and deserialize the data that is passed between the browser and the Web server.
var Names = new JavaScriptSerializer().Deserialize<YourNameClass>(json);
OK I found one! https://github.com/zanders3/json
Has decent tests, minimal features and likely designed for my specific use case.
To load a JSON file:
Dictionary<string, object> locales = new Dictionary<string, object>();
TextAsset file = Resources.Load(name) as TextAsset;
var locale = file.text.FromJson<object>();
locales.Add(name, locale);
To use the JSON dictionary:
string activeLocale = "en-US";
var locale = locales[activeLocale] as Dictionary<string, object>;
var translation = locale[key] as string;
Dead simple.
Super simple Json parsing for Json strings like: { "name1": "David", "name2": "David" }. If you don't need to handle quoted commas and colons, eg {"weapons":"gun,mashine gun,supergun:2"} - change Regex.Split to simple String.Split.
private Dictionary<string, string> ParseJson(string content)
{
content = content.Trim(new[] { '{', '}' }).Replace('\'', '\"');
var trimmedChars = new[] { ' ','\"' };
//regex to split only unquoted separators
Regex regxComma = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");
Regex regxColon = new Regex(":(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");
return regxComma.Split(content)
.Select(v => regxColon.Split(v))
.ToDictionary(v => v.First().Trim(trimmedChars), v => v.Last().Trim(trimmedChars));
}