using System.Collections.Generic;
using Newtonsoft.Json.Linq;
public static void Test()
""headerName1"": ""headerVal1"",
""headerName2"": ""headerVal2"",
""element1Name1"": ""element1Value1""
""element2Name1"": ""element2Value1""
""element3Name1"": ""element3Value1""
""element4Name1"": ""element4Value1""
""element5Name1"": ""element5Value1""
""element6Name1"": ""element6Value1""
""headerNamePost"": ""headerValPost"",
""headerName1"": ""headerVal1"",
""headerName2"": ""headerVal2"",
""element1Name1"": ""element1Value1""
""element2Name1"": ""element2Value1""
""element3Name1"": ""element3Value1""
""element4Name1"": ""element4Value1""
""element5Name1"": ""element5Value1""
""element6Name1"": ""element6Value1""
TestSplitJson(json, "headerName3");
TestSplitJson(json3, "headerName3");
private static void TestSplitJson(string json, string tokenName)
var builders = new List<StringBuilder>();
using (var reader = new StringReader(json))
SplitJson(reader, tokenName, 2, i => { builders.Add(new StringBuilder()); return new StringWriter(builders.Last()); }, Formatting.Indented);
foreach (var s in builders.Select(b => b.ToString()))
AssertCorrect(json, tokenName, builders);
private static void AssertCorrect(string json, string tokenName, List<StringBuilder> builders)
var mainToken = JObject.Parse(json);
foreach (var s in builders.Select(b => b.ToString()))
var token = JObject.Parse(s);
if (!(token.Properties().Select(p => p.Name).SequenceEqual(mainToken.Properties().Select(p => p.Name))))
throw new InvalidOperationException();
if (mainToken[tokenName] != null)
if (!(mainToken[tokenName].SequenceEqual(builders.SelectMany(b => JObject.Parse(b.ToString())[tokenName]), new JTokenEqualityComparer())))
throw new InvalidOperationException();
public static void SplitJson(TextReader textReader, string tokenName, long maxItems, Func<int, TextWriter> createStream, Formatting formatting)
List<JProperty> prefixProperties = new List<JProperty>();
List<JProperty> postFixProperties = new List<JProperty>();
List<JsonWriter> writers = new List<JsonWriter>();
SplitState state = SplitState.InPrefix;
using (var reader = new JsonTextReader(textReader))
while (doRead ? reader.Read() : true)
if (reader.TokenType == JsonToken.Comment || reader.TokenType == JsonToken.None)
if (reader.TokenType != JsonToken.StartObject && reader.TokenType != JsonToken.EndObject)
throw new JsonException("JSON root container is not an Object");
else if (reader.Depth == 1 && reader.TokenType == JsonToken.PropertyName)
if ((string)reader.Value == tokenName)
state = SplitState.InSplitProperty;
if (state == SplitState.InSplitProperty)
state = SplitState.InPostfix;
var property = JProperty.Load(reader);
if (state == SplitState.InPrefix)
prefixProperties.Add(property);
postFixProperties.Add(property);
else if (reader.Depth == 1 && reader.TokenType == JsonToken.StartArray && state == SplitState.InSplitProperty)
state = SplitState.InSplitArray;
else if (reader.Depth == 1 && reader.TokenType == JsonToken.EndArray && state == SplitState.InSplitArray)
state = SplitState.InSplitProperty;
else if (state == SplitState.InSplitArray && reader.Depth == 2)
if (count % maxItems == 0)
var writer = new JsonTextWriter(createStream(writers.Count)) { Formatting = formatting };
writer.WriteStartObject();
foreach (var property in prefixProperties)
property.WriteTo(writer);
writer.WritePropertyName(tokenName);
writer.WriteStartArray();
writers.Last().WriteToken(reader, true);
throw new JsonException("Internal error");
foreach (var writer in writers)
foreach (var property in postFixProperties)
property.WriteTo(writer);
foreach (var writer in writers)
public class JTokenEqualityComparer : IEqualityComparer<JToken>
#region IEqualityComparer<JToken> Members
public bool Equals(JToken x, JToken y)
return JToken.DeepEquals(x, y);
public int GetHashCode(JToken obj)
return obj == null ? 0 : obj.GetHashCode();
public static void Main()