using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public static partial class JsonExtensions
public static string ToUrlEncodedQueryString(this JContainer container)
return container.ToQueryStringKeyValuePairs().ToUrlEncodedQueryString();
public static IEnumerable<KeyValuePair<string, string>> ToQueryStringKeyValuePairs(this JContainer container)
return container.Descendants()
.Select(v => new KeyValuePair<string, string>(v.ToQueryStringParameterName(), (string)v));
public static string ToUrlEncodedQueryString(this IEnumerable<KeyValuePair<string, string>> pairs)
return string.Join("&", pairs.Select(p => HttpUtility.UrlEncode(p.Key) + "=" + HttpUtility.UrlEncode(p.Value)));
public static string ToQueryStringParameterName(this JToken token)
if (token == null || token.Parent == null)
var positions = new List<string>();
for (JToken previous = null, current = token; current != null; previous = current, current = current.Parent)
positions.Add(property.Name);
case JConstructor constructor:
positions.Add(((IList<JToken>)current).IndexOf(previous).ToString(CultureInfo.InvariantCulture));
var sb = new StringBuilder();
for (var i = positions.Count - 1; i >= 0; i--)
sb.Append('[').Append(name).Append(']');
public static void Test()
var jsonString = GetJson();
TestJsonString(jsonString);
var model = JsonConvert.DeserializeObject<ExpandoObject>(jsonString);
Console.WriteLine("Desired query string:");
Console.WriteLine(GetDesiredFormUrlEncodedString());
PrintKeysAndValues2(HttpUtility.ParseQueryString(GetDesiredFormUrlEncodedString()));
static void TestJsonString(string jsonString)
Console.WriteLine("\nTesting JSON string...");
var obj = JObject.Parse(jsonString);
var queryString = obj.ToUrlEncodedQueryString();
Console.WriteLine("Generated query string: ");
Console.WriteLine(queryString);
PrintKeysAndValues2(HttpUtility.ParseQueryString(queryString));
Assert.IsTrue(GetDesiredFormUrlEncodedString().Equals(queryString, StringComparison.OrdinalIgnoreCase));
static void TestDataModel<T>(T myModel)
Console.WriteLine("\nTesting model {0}...", myModel);
var obj = JObject.FromObject(myModel);
var queryString = obj.ToUrlEncodedQueryString();
Console.WriteLine("Generated query string: ");
Console.WriteLine(queryString);
PrintKeysAndValues2(HttpUtility.ParseQueryString(queryString));
Assert.IsTrue(GetDesiredFormUrlEncodedString().Equals(queryString, StringComparison.OrdinalIgnoreCase));
public static void PrintKeysAndValues2( NameValueCollection myCol )
for ( int i = 0; i < myCol.Count; i++ )
Console.WriteLine(" {{ {0}, {1} }} ", JsonConvert.SerializeObject(myCol.GetKey(i)), JsonConvert.SerializeObject(myCol.Get(i)));
Console.WriteLine("}\n");
static string GetDesiredFormUrlEncodedString()
return @"foo=bar&purchase_invoice%5Bdate%5D=14%2F04%2F2015&purchase_invoice%5Bdue_date%5D=14%2F04%2F2015&purchase_invoice%5Bcontact_id%5D=500&purchase_invoice%5Bcontact_name%5D=TestContact&purchase_invoice%5Breference%5D=TestReference&purchase_invoice%5Bline_items_attributes%5D%5B0%5D%5Bunit_price%5D=10&purchase_invoice%5Bline_items_attributes%5D%5B0%5D%5Bquantity%5D=1&purchase_invoice%5Bline_items_attributes%5D%5B0%5D%5Bdescription%5D=TestLineItemAttDesc&purchase_invoice%5Bline_items_attributes%5D%5B0%5D%5Btax_code_id%5D=1&purchase_invoice%5Bline_items_attributes%5D%5B0%5D%5Bledger_account_id%5D=501&purchase_invoice%5Bline_items_attributes%5D%5B0%5D%5Btax_rate_percentage%5D=19&purchase_invoice%5Bline_items_attributes%5D%5B0%5D%5Btax_amount%5D=1.6";
""due_date"":""14/04/2015"",
""contact_name"":""TestContact"",
""reference"":""TestReference"",
""line_items_attributes"":[
""description"":""TestLineItemAttDesc"",
""ledger_account_id"":501,
""tax_rate_percentage"":19.0,
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Assembly.GetName().Name, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.CodeBase.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];