Find string between brackets - c#

I'm having a string that could look like this:
{
"acl_gent": {
"cluster": [],
"indices": [{
"names": ["am*"],
"privileges": ["read", "view_index_metadata"],
"query": "{\"match\": {\"ACL\": \"acl_gent\"}}"
}],
"run_as": []
},
"acl_luik": {
"cluster": [],
"indices": [{
"names": ["am*"],
"privileges": ["read", "view_index_metadata"],
"query": "{\"match\": {\"ACL\": \"acl_luik\"}}"
}],
"run_as": []
}
}
and I would like to split it up in to 2 strings, 1 containing the acl_gent and one conaining acl_luik
the string above can contain more then 2 acl's (and I DON'T know what the name will be)
so I started removing the first and last bracketes :
input = input.Substring(1, input.Length - 2);
but then I can't figure out on how to find the right closing bracket to extract the data.
this was the closest I got
private int closer(string input) {
var i = input.IndexOf('}');
Console.WriteLine(string.Format("[DEBUG] Checking: {0}", input.Substring(0, i).Contains('{')));
if (input.Substring(0, i).Contains('{')) {
return i + closer(input.Substring(i)) + 2;
}
return i;
}

What you have there is a JSON string, a common response from a web service, and there are plenty of libraries to parse JSON, the most common one being JSON.NET. With this you could do something like
JObject myJsonObject = JObject.Parse(myResponse)
and retrieve your strings by their key names, such as
JObject aclString = myJsonObject["acl_luik"];
There are plenty of resources online for parsing JSON strings if you wish to go into more detail.

You have 2 options here:
1) Parse as JSON and get the first 2 objects, this is the better one.
2) Parse using Stack as string of tokens to get what you want, like this:
- Remove the first and last { }
- Using stack, add all { you find, and once you find } remove the first { in the stack.
- Once the stack is empty then you get 1 complete object there, save the indeces while you work and it should be easy to substring with start and end.

I ran into the same problem recently. My solution was to deserialize the string to a json object (in my case a JObject using Json.net) and then accessing the individual members and serializing them to separate strings.
using Newtonsoft.Json.Linq;
public void MakeStrings(string json)
{
var jobject = JsonConvert.DeserializeObject<JObject>(json);
string acl_gent = JsonConvert.SerializeObject(jobject["acl_gent"]);
string acl_luik = JsonConvert.SerializeObject(jobject["acl_luik"]);
}

Related

Newtonsoft.Json.JsonReaderException: Invalid JavaScript property identifier character: ,

I have this code
var list = new List<long>();
long id = 202;
list.Add(2000);
list.Add(2001);
list.Add(2002);
var stringOfIds = string.Join(",", list);
var paramList = #"{'ProjectId':" + id + ", 'EntityIDsList': " + stringOfIds + "}";
Console.WriteLine(paramList);
var parameters = JsonConvert.DeserializeObject<Dictionary<string, object>>(paramList);
Console.WriteLine(parameters);
for some particular reason, it doesn't Deserialize the object and it crashes. What I'm trying here to do is: transform a list of longs into a string, comma separated -> construct the paramList string and then deserialize it using Newtonsoft.Json. I believe that the error is somewhere in the stringOfIds but couldn't figure it out sadly. Do you know what am I doing wrong and how can I fix it?
Right now your paramList looks like this:
{
"ProjectId": 202,
"EntityIDsList":
2000,
2001,
2002
}
Which is not proper JSON. It should look like this:
{
"ProjectId": 202,
"EntityIDsList": [
2000,
2001,
2002
]
}
So you should change it to:
var paramList = #"{'ProjectId':" + id + ", 'EntityIDsList': [" + stringOfIds + "]}";
Also at this point Console.WriteLine(parameters); won't tell you anything meaningfull, you should probably change it to Console.WriteLine(parameters.ToString());
The string you have, paramList is not a valid JSON. JSON object has keys (and values if they are strings) surrounded with double quotes, not single quotes.
Corrected string with escaped double quotes:
#"{""ProjectId"": " + id + #", ""EntityIDsList"": """ + stringOfIds + #"""}";
If your purpose of writing this string is to convert it to an object, you should directly create an object. Also note that you cant print the objects with Console.WriteLine... you will need to convert this to a string first (JsonConvert.SerializeObject) then print it.
var parameters = new
{
ProjectId = id,
EntityIDsList = stringOfIds
};
Console.WriteLine(JsonConvert.SerializeObject(parameters, Formatting.Indented));
// output:
{
"ProjectId": 202,
"EntityIDsList": "2000,2001,2002"
}
If you want EntityIDList as a list of numbers, change the value of EntityIDsList to list instead of stringOfIds.
var parameters2 = new
{
ProjectId = id,
EntityIDsList = list
};
Console.WriteLine(JsonConvert.SerializeObject(parameters2, Formatting.Indented));
//output:
{
"ProjectId": 202,
"EntityIDsList": [
2000,
2001,
2002
]
}
You have two "problems"
you need to add extra single-quotes around the stringOfIds bit
maybe it's actually what you want, but... this will give you a dictionary with 2 items with keys: "ProjectId" and "EnitityIDsList".
As the list is stringified you may as well use D<string, string> (or dynamic, depending on what you're actually trying to do.
I'm guessing you will want to have a collection of "projects"? So the structure in the question won't work.
[
{ "1": "1001,1002" },
{ "2": "2001,2002" }
]
is the normal json form for a dictionary of items
[
{ "1": [1001,1002] },
{ "2": [2001,2002] }
]
into a D<string,List<int>> would be "better".
Strongly suggest you create classes/records to represent the shapes and serialize those. Rather than string concatenation. If you must, then try to use StringBuilder.
Also, although Newtonsoft will handle single quotes, they're not actually part of the spec. You should escape double-quotes into the string if you actually need to generate json this way.
Maybe this is just a cutdown snippet to demo your actual problem and I'm just stating the obvious :D
Just a load of observations.
The extra quotes is the actual "problem" with your sample code.

Simply Beautify a JSON in C# [duplicate]

This question already has answers here:
JSON formatter in C#?
(18 answers)
Closed 3 years ago.
I've searched for a simple native way to beautify a JSON in C# and have fond none, so I did my own and share it here, hope it helps ;)
It transforms condensed JSON like this:
[{"level":1,"exp":110,"energyGranted":5,"itemGranted":null},{"level":2,"exp":195,"energyGranted":5,"itemGranted":null},{"level":3,"exp":296,"energyGranted":5,"itemGranted":null}]
To nice formated JSON like this:
[
{
"level": 1,
"exp": 110,
"energyGranted": 5,
"itemGranted": null
},
{
"level": 2,
"exp": 195,
"energyGranted": 5,
"itemGranted": null
},
{
"level": 3,
"exp": 296,
"energyGranted": 5,
"itemGranted": null
}
]
Context : I was working on a Unity project that handles JSON responses I get from a backend. I didn't want to append some third party C# library just for that simple task.
There is the JsonUtility.ToJson(obj, prettyPrint) Unity built-in method doing that but only from an object, not a JSON, thus my need.
Have you tried converting your string to object then then use ToJson function?
var myObj = JsonUtility.FromJson<YourClass>(jsonString);
var prettyString = JsonUtility.ToJson(myObj);
So here is my solution, it uses Regex groups to split the JSON in multiple lines and depending on the group modifies the indent.
To avoid complicating the regex I'm not dealing with spaces, so it expects a condensed JSON.
using System.Text; // used for StringBuilder, a better string concatenation than myStr += "content"
using System.Text.RegularExpressions;
public static class JsonUtil
{
public static string Beautify(string json)
{
const int indentWidth = 4;
const string pattern = "(?>([{\\[][}\\]],?)|([{\\[])|([}\\]],?)|([^{}:]+:)([^{}\\[\\],]*(?>([{\\[])|,)?)|([^{}\\[\\],]+,?))";
var match = Regex.Match(json, pattern);
var beautified = new StringBuilder();
var indent = 0;
while (match.Success)
{
if (match.Groups[3].Length > 0)
indent--;
beautified.AppendLine(
new string(' ', indent * indentWidth) +
(match.Groups[4].Length > 0
? match.Groups[4].Value + " " + match.Groups[5].Value
: (match.Groups[7].Length > 0 ? match.Groups[7].Value : match.Value))
);
if (match.Groups[2].Length > 0 || match.Groups[6].Length > 0)
indent++;
match = match.NextMatch();
}
return beautified.ToString();
}
}
To use it: var beautifiedJson = JsonUtil.Beautify(json);
It may not be the best solution in terms of performance but it worked perfectly for my use ^^
If you have a better one please take the time to share it ;)

Enumerate a JSON Object and search for and replace data while accompanying EOF

I need to be able to enumerate through ANY kind of JSON, multi-dimensional, one-dimensional, nested, e.t.c and be able to search through BOTH Key, Values e.t.c for <TECH> (.Contains not ==) and replace it with I'm Now Here! "\(^.^)/"
Example:
{"hi":"hello","hi<TECH>":'Lol<TECH>,,,'}
Result should be:
{"hi":"hello","hiI'm Now Here! \"\\(^.^)\/\"":'LolI\'m Now Here! "\\(^.^)\/",,,'}
Im essentially trying to be able to insert data where <TECH> is while properly taking care of \" \ and \' (and others like this).
Again it may not be a single dimensional line it could be nested.
Im trying to JObject.Parse() which allows me to Enumerate through KeyValuePairs but how im meant to send back an edit to the Key/Value im unsure of.
(Also ordering and such is important, I need it to end up being completely the same as the original JSON, formatting and even how its formatted as in one-lined or not has to stay the same)
What I have at the moment
JObject j = JObject.Parse(postData);
foreach (KeyValuePair<string, JToken> item in new JObject(j)) {
string OriginalKey = item.Key.ToString();
string OriginalValue = item.Value.ToString();
string techWord1 = "Other Word's Stuff \":P";
string techWord2 = "I'm Now Here! \"\\(^.^)/\"";
foreach (string techWord in new string[] { "TECH1", "TECH2" }) {
if (OriginalKey.Contains("<" + techWord + ">")) {
j[OriginalKey.Replace("<" + techWord + ">", techWord == "TECH1" ? techWord1 : techWord2)] = j[item.Key];
j.Remove(item.Key);
}
if(OriginalValue.Contains("<" + techWord + ">")) {
j[item.Key] = OriginalValue.Replace("<" + techWord + ">", techWord == "TECH1" ? techWord1 : techWord2);
}
}
}
return j.ToString(Formatting.None);
Issues:
Does not follow the same exact spacing, indenting e.t.c as the original
Don't think it works on nested/multi-dimensional JSON
Don't think every kind of JObject is a KeyValuePair Format? For example how is it going to handle: [{"hi":"value"}, {"hi2":"value2"}]
Other than those, this seems like a good option. It properly parses all kinds of EOF errors that could occur in both Key:Value scenarios. Just need some way to make its .ToString format EXACTLY like the input JSON, for example lets say there were 2 spaces between { and "hi" in the input JSON, the .ToString() would remove that but I need it to KEEP those.

Nested JSON using c# NewtonSoft

Can anyone provide some advice, maybe with a code snippet, using C# and json.net to read some nested json?
My json below validates to good json using JSONLint.
I've hit a hurdle that when parsing the json, I am unable to get into the 3rd, 4th, 6th and 8th values nested in the root.
[{
"interactionType": "MathEditorInteraction",
"interactionId": "08506178-22ba-4fa7-a490-c785716f10dc",
"value": "blah blah blah"
},
{
"interactionType": "MathEditorInteraction",
"interactionId": "1134871f-980e-4138-9598-0d4bf480aa97",
"value": "my first value"
},
{
"interactionType": "CanvasInteraction",
"interactionId": "89cd7bec-d0e8-4111-8442-f2ab95a1410b",
"value": "my second value"
},
{
"interactionType": "FillInBlankInteraction",
"interactionId": "7e9350b4-fb85-4f12-869e-227f99f77a73",
"value": "{\"results\":[{\"id\":\"1ac6770e-2093-4b7c-b595-789be8ee6efb\",\"value\":\"my third value\"}]}"
},
{
"interactionType": "FillInBlankInteraction",
"interactionId": "6f1ca6b7-3178-44a7-b8e9-e82d8c51d1fd",
"value": "{\"results\":[{\"id\":\"b7e92fd2-9c7a-4f71-88f9-e7d43e3179b7\",\"value\":\"my fourth value\"}]}"
},
{
"interactionType": "TextBoxInteraction",
"interactionId": "284c43f9-a268-4295-b96d-bc2f6dc30f0e",
"value": "my fifth value"
},
{
"interactionType": "FillInBlankInteraction",
"interactionId": "544b9907-139a-4c78-9671-502153be2697",
"value": "{\"results\":[{\"id\":\"f4e1ba6d-61dd-4eed-9c6f-dafc2701c161\",\"value\":\"my sixth value\"}]}"
},
{
"interactionType": "TextBoxInteraction",
"interactionId": "c0a5a1f0-2cae-42fd-8726-0ad36c11f413",
"value": "my seventh value"
},
{
"interactionType": "FillInBlankInteraction",
"interactionId": "ef6a7b62-8a7b-4b7f-b876-0d78ee6c4c87",
"value": "{\"results\":[{\"id\":\"af39469e-c041-4889-9e28-61a438cf56a3\",\"value\":\"my eight value\"}]}"
},
{
"interactionType": "TextBoxInteraction",
"interactionId": "f04de5b5-8a29-4200-a886-15f7dbd575b6",
"value": "my nineth value"
}]
then some c# that I've been using:
JArray token = JArray.Parse(response); // response = json string above
for (int i = 0; i < token.Count; i++)
{
String value = token[i]["value"].ToString();
}
I could be surprised with the JSON i consume...it could have n-count nested values...the purpose of my code is to get to the bottom-most child with the "value" string.
Is there a way to look at a token[i]["some string"] and see if it contains a JArray or JObject to continue parsing?
EDIT from Timothy's suggestion, I was able to output the values. Almost there.
static string json2 = #"[{""interactionType"": ""MathEditorInteraction"",""interactionId"": ""08506178-22ba-4fa7-a490-c785716f10dc"",""value"": ""blah blah blah""},{""interactionType"": ""MathEditorInteraction"",""interactionId"": ""1134871f-980e-4138-9598-0d4bf480aa97"",""value"": ""my first value""},{""interactionType"": ""CanvasInteraction"",""interactionId"": ""89cd7bec-d0e8-4111-8442-f2ab95a1410b"",""value"": ""my second value""},{""interactionType"": ""FillInBlankInteraction"",""interactionId"": ""7e9350b4-fb85-4f12-869e-227f99f77a73"",""value"": ""{\""results\"":[{\""id\"":\""1ac6770e-2093-4b7c-b595-789be8ee6efb\"",\""value\"":\""my third value\""}]}""},{""interactionType"": ""FillInBlankInteraction"",""interactionId"": ""6f1ca6b7-3178-44a7-b8e9-e82d8c51d1fd"",""value"": ""{\""results\"":[{\""id\"":\""b7e92fd2-9c7a-4f71-88f9-e7d43e3179b7\"",\""value\"":\""my fourth value\""}]}""},{""interactionType"": ""TextBoxInteraction"",""interactionId"": ""284c43f9-a268-4295-b96d-bc2f6dc30f0e"",""value"": ""my fifth value""},{""interactionType"": ""FillInBlankInteraction"",""interactionId"": ""544b9907-139a-4c78-9671-502153be2697"",""value"": ""{\""results\"":[{\""id\"":\""f4e1ba6d-61dd-4eed-9c6f-dafc2701c161\"",\""value\"":\""my sixth value\""}]}""},{""interactionType"": ""TextBoxInteraction"",""interactionId"": ""c0a5a1f0-2cae-42fd-8726-0ad36c11f413"",""value"": ""my seventh value""},{""interactionType"": ""FillInBlankInteraction"",""interactionId"": ""ef6a7b62-8a7b-4b7f-b876-0d78ee6c4c87"",""value"": ""{\""results\"":[{\""id\"":\""af39469e-c041-4889-9e28-61a438cf56a3\"",\""value\"":\""my eight value\""}]}""},{""interactionType"": ""TextBoxInteraction"",""interactionId"": ""f04de5b5-8a29-4200-a886-15f7dbd575b6"",""value"": ""my ninth value""}]";
var x = JsonConvert.DeserializeObject<Interaction[]>(json2);
for (int i = 0; i < x.Length; i++)
{
if (x[i].value.Contains("[{"))
{
var v = JsonConvert.DeserializeObject<Nested>(x[i].value);
Console.WriteLine(v.results[0].value);
}
else
{
Console.WriteLine(x[i].value);
}
}
Console Output:
blah blah blah
my first value
my second value
my third value
my fourth value
my fifth value
my sixth value
my seventh value
my eight value
my ninth value
Still stuck on actually detecting an array deeper than the first level.
You can see my hack to look for "[{" which is not preferred.
EDIT: KUDOS to Jens for helping me arrive at the solution I needed today. See comments below for full explanations.
You can react to JToken.Type if you don't wish to go into deserializing objects.
I actually mostly work with the JSON in a dynamic fasion in C# my self, never deserializing it into strong types, this is mostly because we work with backends where the data structures are defined by the clients and we need to be able to handle much more dynamic data.
https://dotnetfiddle.net/awUSGT
dynamic arr = JArray.Parse(JSON); // response = json string above
foreach (dynamic token in arr)
{
JTokenType type = ((JToken)token.value).Type;
switch (type)
{
case JTokenType.String:
Console.WriteLine(token.value);
break;
case JTokenType.Object:
Console.WriteLine(token.value.results.Last.value);
break;
}
}
Note that for before 8.x or 9.x (can't remember when I posted that fix) something the above will thrown an exception when casting to JToken.
So can instead do:
dynamic arr = JArray.Parse(JSON); // response = json string above
foreach (JObject token in arr)
{
dynamic value = token["value"];
switch (token["value"].Type)
{
case JTokenType.String:
Console.WriteLine(value);
break;
case JTokenType.Object:
Console.WriteLine(value.results.Last.value);
break;
}
}
Now as for one final note, the tool i used to prettify your JSON seemed to strip away some escaping for your values.
I don't know if it was intentional that you have your embeded JSON as strings (Serialized JSON), if so you need to find a way to discover that and then parse that as well.
A loose/relaxed approach could be:
dynamic arr = JArray.Parse(JSON); // response = json string above
foreach (dynamic token in arr)
{
string tokenvalue = (string) token.value;
JToken value = Regex.IsMatch(tokenvalue, "^\\{.*\\}$")
? JToken.Parse(tokenvalue)
: token.value;
switch (value.Type)
{
case JTokenType.String:
Console.WriteLine(value);
break;
case JTokenType.Object:
Console.WriteLine(((dynamic)value).results.Last.value);
break;
}
}
Since I don't know exactly how your "recursive nesting" looks, it is hard to guess, but something along the lines of:
public static void Main()
{
dynamic arr = JArray.Parse(JSON); // response = json string above
foreach (dynamic token in arr)
{
JToken value = ExtractValue(token);
Console.WriteLine(value);
}
}
private static JToken ExtractValue(dynamic token)
{
string tokenvalue = (string) token.value;
JToken value = Regex.IsMatch(tokenvalue, "^\\{.*\\}$")
? JToken.Parse(tokenvalue)
: token.value;
switch (value.Type)
{
case JTokenType.String:
return value;
case JTokenType.Object:
return ExtractValue(((dynamic) value).results.Last);
default:
throw new InvalidOperationException("Could not extract data, unknown json construct.");
}
}
Maybe.
You can easily generate model classes using this service
With this model you can easily Deserialize using Newtonsoft Json
Try using this: JsonConvert.DeserializeObject<Interaction[]>(yourJson);
where Interaction is:
public class Interaction
{
public string interactionType {get;set;}
public string interactionId {get;set;}
public string value {get;set;}
}
Then, for the ones that have a nested JSON, you can then simply parse the value property of them as the following:
public class Nested
{
public Result[] results {get;set;}
}
public class Result
{
public string id {get;set;}
public string value {get;set;}
}
Then parse it like this:
var v = JsonConvert.DeserializeObject<Nested>(x[8].value);

how to normalise json from javascript in c#

hello there i have this following j.s .. i am sending an array to my C# file in r in json format
var r=['maths','computer','physics']
$.post("Global.aspx", { opt: "postpost", post: w.val(),tags:JSON.stringify(r)
}, function (d) {
});
but in c# i am getting this type of string:
["Maths""Computer""Physics"]
.
i want only the words maths,computer,physics not the [ sign and " sign .. please help me out
i have following c# code :
string[] _tags = Request.Form["tags"].ToString().Split(',');
string asd="";
foreach (string ad in _tags) {
asd += ad;
}
You're looking for JSON deserialization:
List<string> list = new JavaScriptSerializer().Deserialize<List<string>>(Request.Form["tags"]);
As pointed out, you've split your string on the , character leaving you with an array of:
[0] = "[\"Maths\""
[1] = "\"Computer\""
[2] = "\"Physics\"]"
Because JSON is a data type, those square brackets actually have functional meaning. They're not just useless extra characters. As such, you need to parse the data into a format you can actually work that.

Categories