public void ArrayItems_FilteringByIndexAndValue_ReturnsSplitSequences() { var input = new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenFalse, ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("key1"), ModelGrammar.TokenNull, ModelGrammar.TokenProperty("key2"), ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenObjectEnd, ModelGrammar.TokenPrimitive(42), ModelGrammar.TokenPrimitive(Math.PI), ModelGrammar.TokenArrayEnd }; var expected = new[] { new[] { ModelGrammar.TokenFalse }, new[] { ModelGrammar.TokenPrimitive(Math.PI), } }; // select all even index primitive items var actual = input.ArrayItems(index => (index % 2 == 0)).Where(item => item.IsPrimitive()).ToArray(); Assert.Equal(expected, actual, false); }
private void GetArrayTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, IEnumerable value) { DataName typeName = this.GetTypeName(value); IEnumerator enumerator = value.GetEnumerator(); if (enumerator is IEnumerator <KeyValuePair <string, object> > ) { this.GetObjectTokens(tokens, detector, typeName, (IEnumerator <KeyValuePair <string, object> >)enumerator); return; } if (enumerator is IDictionaryEnumerator) { this.GetObjectTokens(tokens, detector, typeName, (IDictionaryEnumerator)enumerator); return; } tokens.Add(ModelGrammar.TokenArrayBegin(typeName)); while (enumerator.MoveNext()) { this.GetTokens(tokens, detector, enumerator.Current); } tokens.Add(ModelGrammar.TokenArrayEnd); }
public void ArrayItems_IndexFilter_ReturnsSplitSequences() { var input = new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenFalse, ModelGrammar.TokenPrimitive("Pick me!"), ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("key1"), ModelGrammar.TokenNull, ModelGrammar.TokenProperty("key2"), ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenObjectEnd, ModelGrammar.TokenPrimitive(42), ModelGrammar.TokenArrayEnd }; var expected = new[] { new[] { ModelGrammar.TokenPrimitive("Pick me!") }, new[] { ModelGrammar.TokenPrimitive(42) } }; // select items with odd indexes var actual = input.ArrayItems(index => (index % 2 == 1)).ToArray(); Assert.Equal(expected, actual, false); }
public void ObjectProperties_NestedArrayPropertyReturned_ReturnsSplitSequences() { var input = new[] { ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("key1"), ModelGrammar.TokenNull, ModelGrammar.TokenProperty("key2"), ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenFalse, ModelGrammar.TokenPrimitive(42), ModelGrammar.TokenArrayEnd, ModelGrammar.TokenProperty("three"), ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenProperty("4"), ModelGrammar.TokenTrue, ModelGrammar.TokenObjectEnd }; var expected = new Dictionary <DataName, IEnumerable <Token <ModelTokenType> > > { { new DataName("key2"), new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenFalse, ModelGrammar.TokenPrimitive(42), ModelGrammar.TokenArrayEnd, } } }; // select all properties var actual = input.Properties(name => name.LocalName == "key2").ToArray(); Assert.Equal(expected, actual, false); }
public void IsPrimitive_StringPrimitive_ReturnsTrue() { var input = new[] { ModelGrammar.TokenPrimitive("Hello.") }; Assert.True(input.IsPrimitive()); }
public void IsArray_StringPrimitive_ReturnsFalse() { var input = new[] { ModelGrammar.TokenPrimitive("Hello.") }; Assert.False(input.IsArray()); }
private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, DataName typeName, IDictionaryEnumerator enumerator) { tokens.Add(ModelGrammar.TokenObjectBegin(typeName)); while (enumerator.MoveNext()) { tokens.Add(ModelGrammar.TokenProperty(enumerator.Key)); this.GetTokens(tokens, detector, enumerator.Value); } tokens.Add(ModelGrammar.TokenObjectEnd); }
private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, DataName typeName, IEnumerator <KeyValuePair <string, object> > enumerator) { tokens.Add(ModelGrammar.TokenObjectBegin(typeName)); while (enumerator.MoveNext()) { KeyValuePair <string, object> pair = enumerator.Current; tokens.Add(ModelGrammar.TokenProperty(pair.Key)); this.GetTokens(tokens, detector, pair.Value); } tokens.Add(ModelGrammar.TokenObjectEnd); }
public void Descendants_NestedObjectsFindDescendantsWithProperty_ReturnsMatchingSubsequences() { var input = new[] { ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("One"), ModelGrammar.TokenNull, ModelGrammar.TokenProperty("Two"), ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenTrue, ModelGrammar.TokenPrimitive("2-B"), ModelGrammar.TokenPrimitive(23), ModelGrammar.TokenArrayEnd, ModelGrammar.TokenProperty("Three"), ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("A"), ModelGrammar.TokenPrimitive("3-A"), ModelGrammar.TokenProperty("B"), ModelGrammar.TokenPrimitive(32), ModelGrammar.TokenProperty("C"), ModelGrammar.TokenPrimitive("3-C"), ModelGrammar.TokenObjectEnd, ModelGrammar.TokenProperty("Four"), ModelGrammar.TokenPrimitive(4), ModelGrammar.TokenObjectEnd }; var expected = new[] { new[] { ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("A"), ModelGrammar.TokenPrimitive("3-A"), ModelGrammar.TokenProperty("B"), ModelGrammar.TokenPrimitive(32), ModelGrammar.TokenProperty("C"), ModelGrammar.TokenPrimitive("3-C"), ModelGrammar.TokenObjectEnd } }; // select all descendants with property named "B" var actual = input.Descendants().Where(child => child.HasProperty(name => name.LocalName == "B")).ToArray(); Assert.Equal(expected, actual, false); }
public void ArrayItems_NestedArray_ReturnsSplitSequences() { var input = new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenFalse, ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenFalse, ModelGrammar.TokenNull, ModelGrammar.TokenTrue, ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenPrimitive(42), ModelGrammar.TokenArrayEnd, ModelGrammar.TokenPrimitive(42), ModelGrammar.TokenArrayEnd }; var expected = new[] { new[] { ModelGrammar.TokenFalse }, new[] { ModelGrammar.TokenPrimitive("Hello!") }, new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenFalse, ModelGrammar.TokenNull, ModelGrammar.TokenTrue, ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenPrimitive(42), ModelGrammar.TokenArrayEnd, }, new[] { ModelGrammar.TokenPrimitive(42) }, }; // select all items var actual = input.ArrayItems(index => true).ToArray(); Assert.Equal(expected, actual, false); }
private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, Type type, System.Dynamic.DynamicObject value) { DataName typeName = this.GetTypeName(value); tokens.Add(ModelGrammar.TokenObjectBegin(typeName)); foreach (var memberName in value.GetDynamicMemberNames()) { object propertyValue; if (!value.TryGetMember(new DynamicGetter(memberName), out propertyValue)) { continue; } tokens.Add(ModelGrammar.TokenProperty(memberName)); this.GetTokens(tokens, detector, propertyValue); } tokens.Add(ModelGrammar.TokenObjectEnd); }
public void ArrayItems_MixedPrimitivesFilterAll_ReturnsSplitSequences() { var input = new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenFalse, ModelGrammar.TokenTrue, ModelGrammar.TokenNull, ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenNull, ModelGrammar.TokenPrimitive(42), ModelGrammar.TokenArrayEnd }; var expected = new IEnumerable <Token <ModelTokenType> > [0]; // select no items var actual = input.ArrayItems(index => false).ToArray(); Assert.Equal(expected, actual, false); }
public void HasProperty_PickNonExisting_ReturnsFalse() { var input = new[] { ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("key1"), ModelGrammar.TokenNull, ModelGrammar.TokenProperty("key2"), ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenProperty("three"), ModelGrammar.TokenPrimitive(3), ModelGrammar.TokenProperty("4"), ModelGrammar.TokenTrue, ModelGrammar.TokenObjectEnd }; // test for a specific property var actual = input.HasProperty(name => name.LocalName == "five"); Assert.False(actual); }
private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, Type type, object value) { DataName typeName = this.GetTypeName(value); tokens.Add(ModelGrammar.TokenObjectBegin(typeName)); IDictionary <string, MemberMap> maps = this.Settings.Resolver.LoadMaps(type); if (maps == null) { // TODO: verify no other valid situations here tokens.Add(ModelGrammar.TokenObjectEnd); return; } // allow the resolver to optionally sort the members IEnumerable <MemberMap> members = this.Settings.Resolver.SortMembers(maps.Values); foreach (var map in members) { if (map.IsAlternate || map.Getter == null) { continue; } object propertyValue = map.Getter(value); if (map.IsIgnored != null && map.IsIgnored(value, propertyValue)) { continue; } tokens.Add(ModelGrammar.TokenProperty(map.DataName)); this.GetTokens(tokens, detector, propertyValue); } tokens.Add(ModelGrammar.TokenObjectEnd); }
public void ArrayItems_MixedPrimitivesFilterNonNull_ReturnsSplitSequences() { var input = new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenFalse, ModelGrammar.TokenTrue, ModelGrammar.TokenNull, ModelGrammar.TokenPrimitive("Hello!"), ModelGrammar.TokenNull, ModelGrammar.TokenPrimitive(42), ModelGrammar.TokenArrayEnd }; var expected = new[] { new[] { ModelGrammar.TokenFalse }, new[] { ModelGrammar.TokenTrue }, new[] { ModelGrammar.TokenPrimitive("Hello!") }, new[] { ModelGrammar.TokenPrimitive(42) }, }; // select all items with a non-null value var actual = input.ArrayItems().Where(item => item.All(token => token.Value != null)).ToArray(); Assert.Equal(expected, actual, false); }
private void GetTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, object value) { if (value == null) { tokens.Add(ModelGrammar.TokenNull); return; } // test for cycles if (detector.Add(value)) { switch (this.Settings.GraphCycles) { case GraphCycleType.Reference: { // no need to remove value as was duplicate reference throw new GraphCycleException(GraphCycleType.Reference, "Graph cycle detected: repeated references"); } case GraphCycleType.MaxDepth: { throw new GraphCycleException(GraphCycleType.MaxDepth, "Graph cycle potentially detected: maximum depth exceeded"); } default: case GraphCycleType.Ignore: { // no need to remove value as was duplicate reference // replace cycle with null tokens.Add(ModelGrammar.TokenNull); return; } } } try { foreach (var filter in this.Filters) { IEnumerable <Token <ModelTokenType> > filterResult; if (filter.TryWrite(this.Settings, value, out filterResult)) { // found a successful match tokens.AddRange(filterResult); return; } } Type type = value.GetType(); // must test enumerations before other value types if (type.IsEnum) { tokens.Add(ModelGrammar.TokenPrimitive((Enum)value)); return; } // Type.GetTypeCode() allows us to more efficiently switch type switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: { tokens.Add(true.Equals(value) ? ModelGrammar.TokenTrue : ModelGrammar.TokenFalse); return; } case TypeCode.Byte: case TypeCode.Decimal: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.SByte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: { tokens.Add(ModelGrammar.TokenPrimitive((ValueType)value)); return; } case TypeCode.Double: { double doubleVal = (double)value; if (Double.IsNaN(doubleVal)) { tokens.Add(ModelGrammar.TokenNaN); } else if (Double.IsPositiveInfinity(doubleVal)) { tokens.Add(ModelGrammar.TokenPositiveInfinity); } else if (Double.IsNegativeInfinity(doubleVal)) { tokens.Add(ModelGrammar.TokenNegativeInfinity); } else { tokens.Add(ModelGrammar.TokenPrimitive(doubleVal)); } return; } case TypeCode.Single: { float floatVal = (float)value; if (Single.IsNaN(floatVal)) { // use the Double equivalent tokens.Add(ModelGrammar.TokenNaN); } else if (Single.IsPositiveInfinity(floatVal)) { // use the Double equivalent tokens.Add(ModelGrammar.TokenPositiveInfinity); } else if (Single.IsNegativeInfinity(floatVal)) { // use the Double equivalent tokens.Add(ModelGrammar.TokenNegativeInfinity); } else { tokens.Add(ModelGrammar.TokenPrimitive(floatVal)); } return; } case TypeCode.Char: case TypeCode.DateTime: case TypeCode.String: { tokens.Add(ModelGrammar.TokenPrimitive(value)); return; } case TypeCode.DBNull: case TypeCode.Empty: { tokens.Add(ModelGrammar.TokenNull); return; } } if (value is IEnumerable) { this.GetArrayTokens(tokens, detector, (IEnumerable)value); return; } if (value is Guid || value is Uri || value is Version) { tokens.Add(ModelGrammar.TokenPrimitive(value)); return; } if (value is TimeSpan) { tokens.Add(ModelGrammar.TokenPrimitive((TimeSpan)value)); return; } #if NET40 && !WINDOWS_PHONE if (value is System.Dynamic.DynamicObject) { // TODO: expand to all IDynamicMetaObjectProvider? this.GetObjectTokens(tokens, detector, type, (System.Dynamic.DynamicObject)value); return; } #endif // all other structs and classes this.GetObjectTokens(tokens, detector, type, value); } finally { detector.Remove(value); } }
public void Descendants_NestedObjects_ReturnsAllSubsequences() { var input = new[] { ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("One"), ModelGrammar.TokenNull, ModelGrammar.TokenProperty("Two"), ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenTrue, ModelGrammar.TokenPrimitive("2-B"), ModelGrammar.TokenPrimitive(23), ModelGrammar.TokenArrayEnd, ModelGrammar.TokenProperty("Three"), ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("A"), ModelGrammar.TokenPrimitive("3-A"), ModelGrammar.TokenProperty("B"), ModelGrammar.TokenPrimitive(32), ModelGrammar.TokenProperty("C"), ModelGrammar.TokenPrimitive("3-C"), ModelGrammar.TokenObjectEnd, ModelGrammar.TokenProperty("Four"), ModelGrammar.TokenPrimitive(4), ModelGrammar.TokenObjectEnd }; var expected = new[] { new[] { ModelGrammar.TokenNull }, new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenTrue, ModelGrammar.TokenPrimitive("2-B"), ModelGrammar.TokenPrimitive(23), ModelGrammar.TokenArrayEnd }, new[] { ModelGrammar.TokenTrue }, new[] { ModelGrammar.TokenPrimitive("2-B") }, new[] { ModelGrammar.TokenPrimitive(23) }, new[] { ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("A"), ModelGrammar.TokenPrimitive("3-A"), ModelGrammar.TokenProperty("B"), ModelGrammar.TokenPrimitive(32), ModelGrammar.TokenProperty("C"), ModelGrammar.TokenPrimitive("3-C"), ModelGrammar.TokenObjectEnd }, new[] { ModelGrammar.TokenPrimitive("3-A") }, new[] { ModelGrammar.TokenPrimitive(32) }, new[] { ModelGrammar.TokenPrimitive("3-C") }, new[] { ModelGrammar.TokenPrimitive(4), } }; // select all descendants var actual = input.Descendants().ToArray(); Assert.Equal(expected, actual, false); }
public void Properties_GraphComplex_ReturnsGraph() { // input from pass1.json in test suite at http://www.json.org/JSON_checker/ var input = new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenPrimitive("JSON Test Pattern pass1"), ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("object with 1 member"), ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenPrimitive("array with 1 element"), ModelGrammar.TokenArrayEnd, ModelGrammar.TokenObjectEnd, ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenObjectEnd, ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenArrayEnd, ModelGrammar.TokenPrimitive(-42), ModelGrammar.TokenTrue, ModelGrammar.TokenFalse, ModelGrammar.TokenNull, ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenProperty("integer"), ModelGrammar.TokenPrimitive(1234567890), ModelGrammar.TokenProperty("real"), ModelGrammar.TokenPrimitive(-9876.543210), ModelGrammar.TokenProperty("e"), ModelGrammar.TokenPrimitive(0.123456789e-12), ModelGrammar.TokenProperty("E"), ModelGrammar.TokenPrimitive(1.234567890E+34), ModelGrammar.TokenProperty(""), ModelGrammar.TokenPrimitive(23456789012E66), ModelGrammar.TokenProperty("zero"), ModelGrammar.TokenPrimitive(0), ModelGrammar.TokenProperty("one"), ModelGrammar.TokenPrimitive(1), ModelGrammar.TokenProperty("space"), ModelGrammar.TokenPrimitive(" "), ModelGrammar.TokenProperty("quote"), ModelGrammar.TokenPrimitive("\""), ModelGrammar.TokenProperty("backslash"), ModelGrammar.TokenPrimitive("\\"), ModelGrammar.TokenProperty("controls"), ModelGrammar.TokenPrimitive("\b\f\n\r\t"), ModelGrammar.TokenProperty("slash"), ModelGrammar.TokenPrimitive("/ & /"), ModelGrammar.TokenProperty("alpha"), ModelGrammar.TokenPrimitive("abcdefghijklmnopqrstuvwyz"), ModelGrammar.TokenProperty("ALPHA"), ModelGrammar.TokenPrimitive("ABCDEFGHIJKLMNOPQRSTUVWYZ"), ModelGrammar.TokenProperty("digit"), ModelGrammar.TokenPrimitive("0123456789"), ModelGrammar.TokenProperty("0123456789"), ModelGrammar.TokenPrimitive("digit"), ModelGrammar.TokenProperty("special"), ModelGrammar.TokenPrimitive("`1~!@#$%^&*()_+-={':[,]}|;.</>?"), ModelGrammar.TokenProperty("hex"), ModelGrammar.TokenPrimitive("\u0123\u4567\u89AB\uCDEF\uabcd\uef4A"), ModelGrammar.TokenProperty("true"), ModelGrammar.TokenTrue, ModelGrammar.TokenProperty("false"), ModelGrammar.TokenFalse, ModelGrammar.TokenProperty("null"), ModelGrammar.TokenNull, ModelGrammar.TokenProperty("array"), ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenArrayEnd, ModelGrammar.TokenProperty("object"), ModelGrammar.TokenObjectBeginUnnamed, ModelGrammar.TokenObjectEnd, ModelGrammar.TokenProperty("address"), ModelGrammar.TokenPrimitive("50 St. James Street"), ModelGrammar.TokenProperty("url"), ModelGrammar.TokenPrimitive("http://www.JSON.org/"), ModelGrammar.TokenProperty("comment"), ModelGrammar.TokenPrimitive("// /* <!-- --"), ModelGrammar.TokenProperty("# -- --> */"), ModelGrammar.TokenPrimitive(" "), ModelGrammar.TokenProperty(" s p a c e d "), ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenPrimitive(1), ModelGrammar.TokenPrimitive(2), ModelGrammar.TokenPrimitive(3), ModelGrammar.TokenPrimitive(4), ModelGrammar.TokenPrimitive(5), ModelGrammar.TokenPrimitive(6), ModelGrammar.TokenPrimitive(7), ModelGrammar.TokenArrayEnd, ModelGrammar.TokenProperty("compact"), ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenPrimitive(1), ModelGrammar.TokenPrimitive(2), ModelGrammar.TokenPrimitive(3), ModelGrammar.TokenPrimitive(4), ModelGrammar.TokenPrimitive(5), ModelGrammar.TokenPrimitive(6), ModelGrammar.TokenPrimitive(7), ModelGrammar.TokenArrayEnd, ModelGrammar.TokenProperty("jsontext"), ModelGrammar.TokenPrimitive("{\"object with 1 member\":[\"array with 1 element\"]}"), ModelGrammar.TokenProperty("quotes"), ModelGrammar.TokenPrimitive("" \u0022 %22 0x22 034 ""), ModelGrammar.TokenProperty("/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"), ModelGrammar.TokenPrimitive("A key can be any string"), ModelGrammar.TokenObjectEnd, ModelGrammar.TokenPrimitive(0.5), ModelGrammar.TokenPrimitive(98.6), ModelGrammar.TokenPrimitive(99.44), ModelGrammar.TokenPrimitive(1066), ModelGrammar.TokenPrimitive(10.0), ModelGrammar.TokenPrimitive(1.0), ModelGrammar.TokenPrimitive(0.1), ModelGrammar.TokenPrimitive(1.0), ModelGrammar.TokenPrimitive(2.0), ModelGrammar.TokenPrimitive(2.0), ModelGrammar.TokenPrimitive("rosebud"), ModelGrammar.TokenArrayEnd }; var expected = new Dictionary <DataName, IEnumerable <Token <ModelTokenType> > > { { new DataName("url"), new[] { ModelGrammar.TokenPrimitive("http://www.JSON.org/") } }, { new DataName("compact"), new[] { ModelGrammar.TokenArrayBeginUnnamed, ModelGrammar.TokenPrimitive(1), ModelGrammar.TokenPrimitive(2), ModelGrammar.TokenPrimitive(3), ModelGrammar.TokenPrimitive(4), ModelGrammar.TokenPrimitive(5), ModelGrammar.TokenPrimitive(6), ModelGrammar.TokenPrimitive(7), ModelGrammar.TokenArrayEnd, } } }; Assert.True(input.IsArray()); Assert.False(input.IsObject()); Assert.False(input.IsPrimitive()); // cherry pick properties var actual = input .ArrayItems(index => index == 8).FirstOrDefault() // select the big object .Properties(name => name.LocalName == "url" || name.LocalName == "compact"); // select two properties Assert.Equal(expected, actual, false); }