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));
}
Related
I'm trying to learn c# Json.net and I want to create a JSON multiline string that includes string declarations, but the first curly bracket which is meant to be part of the JSON dictionary is including itself in the declaration. It errors me on the 'name', if anyone can please give me a solution that would be great.
here is the code.
string Name = "'Name'";
string Is_Airing = "True";
string Genre_One = "'Yes'";
string Genre_Two = "'No'";
string Json_String = $#"{
'Name': '{Name}',
'Is_Airing': {Is_Airing},
'Genres': [
'{Genre_One}',
'{Genre_Two}'
]
}";
If your heart is set on DIY, double up the brackets to escape {{, but you're really [doing a poor job of] reinventing the wheel compared to using a serializer and chucking something like an anonymous or proper type into it:
//newtonsoft
JsonConvert.SerializeObject(new {
Name, //gets name of property from name of variable
Is_Airing = MyIsAiringVariableName, //specifies name of property in anonymous type
Genres = new []{
Genre_One,
Genre_Two
}
});
'Name': '{Name}',
JSON uses double quotes, by the way.. And typically uses camelCase names. Usign a serializer will ensure better compliance with standard JSON ("be strict in what you send and liberal in what you accept")
For more control over how the output JSON appears, you set options on the serializer (such as passing Formatting.Indented as the second argument to SerializeObject), or decorate your properties with attributes
The Newtonsoft documentation is quite comprehensive and includes useful samples to get you going: https://www.newtonsoft.com/json/help/html/SerializeObject.htm
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.
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.
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.
I am querying a web service that was built by another developer. It returns a result set in a JSON-like format. I get three column values (I already know what the ordinal position of each column means):
[["Boston","142","JJK"],["Miami","111","QLA"],["Sacramento","042","PPT"]]
In reality, this result set can be thousands of records long.
What's the best way to parse this string?
I guess a JSON deserializer would be nice, but what is a good one to use in C#/.NET? I'm pretty sure the System.Runtime.Serialization.Json serializer won't work.
Using the built in libraries for asp.net (System.Runtime.Serialization and System.ServiceModel.Web) you can get what you want pretty easily:
string[][] parsed = null;
var jsonStr = #"[[""Boston"",""142"",""JJK""],[""Miami"",""111"",""QLA""],[""Sacramento"",""042"",""PPT""]]";
using (var ms = new System.IO.MemoryStream(System.Text.Encoding.Default.GetBytes(jsonStr)))
{
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(string[][]));
parsed = serializer.ReadObject(ms) as string[][];
}
A little more complex example (which was my original answer)
First make a dummy class to use for serialization. It just needs one member to hold the result which should be of type string[][].
[DataContract]
public class Result
{
[DataMember(Name="d")]
public string[][] d { get; set; }
}
Then it's as simple as wrapping your result up like so: { "d": /your results/ }. See below for an example:
Result parsed = null;
var jsonStr = #"[[""Boston"",""142"",""JJK""],[""Miami"",""111"",""QLA""],[""Sacramento"",""042"",""PPT""]]";
using (var ms = new MemoryStream(Encoding.Default.GetBytes(string.Format(#"{{ ""d"": {0} }}", jsonStr))))
{
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(Result));
parsed = serializer.ReadObject(ms) as Result;
}
How about this?
It sounds like you have a pretty simple format that you could write a custom parser for, since you don't always want to wait for it to parse and return the entire thing before it uses it.
I would just write a recursive parser that looks for the tokens "[", ",", "\"", and "]" and does the appropriate thing.