/// <summary> /// <see cref="JSONEntity"/> => JSON <see cref="string"/> conversion. /// </summary> /// <param name="entity">The <see cref="JSONEntity"/> to be converted.</param> /// <returns>The JSON <see cref="string"/> converted.</returns> internal static string Analyze(JSONEntity entity) { StringBuilder sb = new StringBuilder(); switch (entity.EntityType) { case JSONEntityType.Dictionary: sb.Append(Constants.Tokens.JSONDictionaryStart); sb.Append(string.Join(Constants.Tokens.JSONSeparator, from e in entity.AsDictionary() select $"{Constants.Characters.QUOTE}{e.Key}{Constants.Characters.QUOTE}{Constants.Tokens.JSONDictionaryKey}{Analyze(e.Value)}")); sb.Append(Constants.Tokens.JSONDictionaryEnd); break; case JSONEntityType.List: sb.Append(Constants.Tokens.JSONListStart); sb.Append(string.Join(Constants.Tokens.JSONSeparator, from e in entity.AsList() select Analyze(e))); sb.Append(Constants.Tokens.JSONListEnd); break; case JSONEntityType.Primitive: object v = entity.AsPrimitive(); if (v is string) { sb.Append(Constants.Characters.QUOTE); sb.Append(v as string); sb.Append(Constants.Characters.QUOTE); } else if (v is bool) { sb.Append(v as bool? ?? default ? Constants.Tokens.JSONPrimitiveTrue : Constants.Tokens.JSONPrimitiveFalse); } else { sb.Append(System.Convert.ToString(v)); } break; case JSONEntityType.Void: sb.Append(Constants.Tokens.JSONVoidNull); break; default: break; } return(sb.ToString()); }
/// <summary> /// JSON <see cref="string"/> => <see cref="JSONEntity"/> conversion. /// </summary> /// <param name="str">The JSON <see cref="string"/> to be converted.</param> /// <returns>The <see cref="JSONEntity"/> converted.</returns> internal static JSONEntity Analyze(string str) { if (str is null) { goto exit_with_void; } str = str.Trim(); if (!str.StartsWith(Constants.Tokens.JSONDictionaryStart) && !str.StartsWith(Constants.Tokens.JSONListStart)) { return(Convert.FromString(str)); } Stack <JSONEntity> bases = new Stack <JSONEntity>(); Stack <string> keys = new Stack <string>(); StringBuilder sb = new StringBuilder(); char last_token = Constants.Characters.NULL; bool exist_string = false; foreach (var c in str) { if (Constants.Characters.QUOTE == last_token || Constants.Characters.APOSTROPHE == last_token) { if (last_token == c) { last_token = Constants.Characters.NULL; } sb.Append(c); continue; } switch (c) { case Constants.Characters.QUOTE: case Constants.Characters.APOSTROPHE: sb.Append(c); exist_string = true; last_token = c; break; case Constants.Tokens.JSONDictionaryStart: bases.Push(JSONEntity.Dictionary()); last_token = c; break; case Constants.Tokens.JSONListStart: bases.Push(JSONEntity.List()); last_token = c; break; case Constants.Tokens.JSONDictionaryKey: var tkey = sb.ToString(); keys.Push((tkey.SurroundedWith(Constants.Characters.APOSTROPHE) || tkey.SurroundedWith(Constants.Characters.QUOTE) ? tkey.Substring(1, tkey.Length - 2) : tkey).Unescape());; sb.Clear(); last_token = c; break; case Constants.Tokens.JSONSeparator: if (0 < sb.Length || exist_string || (Constants.Tokens.JSONDictionaryEnd != last_token && Constants.Tokens.JSONListEnd != last_token && 0 < bases.Count)) { JSONEntity current_entity = bases.Peek(); if (current_entity.IsDictionary) { current_entity.AsDictionary().Add(keys.Pop(), Convert.FromString(sb.ToString())); } else if (current_entity.IsList) { current_entity.AsList().Add(Convert.FromString(sb.ToString())); } sb.Clear(); exist_string = false; } last_token = c; break; case Constants.Tokens.JSONDictionaryEnd: JSONEntity current_dictionary = bases.Pop(); if (0 < sb.Length || exist_string || Constants.Tokens.JSONDictionaryKey == last_token) { current_dictionary.AsDictionary().Add(keys.Pop(), Convert.FromString(sb.ToString())); sb.Clear(); exist_string = false; } last_token = c; if (0 >= bases.Count) { return(current_dictionary); } else { JSONEntity base_entity = bases.Peek(); if (base_entity.IsDictionary) { base_entity.AsDictionary().Add(keys.Pop(), current_dictionary); } else if (base_entity.IsList) { base_entity.AsList().Add(current_dictionary); } } break; case Constants.Tokens.JSONListEnd: JSONEntity current_list = bases.Pop(); if (0 < sb.Length || exist_string || Constants.Tokens.JSONSeparator == last_token) { current_list.AsList().Add(Convert.FromString(sb.ToString())); sb.Clear(); exist_string = false; } last_token = c; if (0 >= bases.Count) { return(current_list); } else { JSONEntity base_entity = bases.Peek(); if (base_entity.IsDictionary) { base_entity.AsDictionary().Add(keys.Pop(), current_list); } else if (base_entity.IsList) { base_entity.AsList().Add(current_list); } } break; default: if (0 < sb.Length) { last_token = Constants.Characters.NULL; sb.Append(c); } else if (c.IsVisibleAndNotSpace()) { last_token = Constants.Characters.NULL; exist_string = false; sb.Append(c); } break; } } exit_with_void: return(JSONEntity.Void); }