Last active
February 15, 2016 18:30
-
-
Save bleroy/a5f48372320c3bdb84ad to your computer and use it in GitHub Desktop.
Helper methods for use with Newtonsoft's JSON library.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Newtonsoft.Json; | |
using System.Collections.Generic; | |
namespace Bleroy | |
{ | |
public static class JsonHelpers | |
{ | |
/// <summary> | |
/// Advances the reader to the first child property with the provided name, | |
/// no matter how deep it is. | |
/// After calling this method, the cursor is on the value node. | |
/// </summary> | |
/// <param name="reader">The reader.</param> | |
/// <param name="property">The name of the property to search for.</param> | |
/// <returns>True if a node of that type was found.</returns> | |
public static bool AdvanceTo(this JsonTextReader reader, string property) | |
{ | |
var depth = 0; | |
while (reader.Read() && depth >= 0) { | |
if (reader.TokenType == JsonToken.PropertyName | |
&& (string)reader.Value == property) | |
{ | |
reader.Read(); | |
return true; | |
} | |
switch (reader.TokenType) | |
{ | |
case JsonToken.StartObject: | |
case JsonToken.StartArray: | |
case JsonToken.StartConstructor: | |
depth++; | |
break; | |
case JsonToken.EndObject: | |
case JsonToken.EndArray: | |
case JsonToken.EndConstructor: | |
depth--; | |
break; | |
} | |
} | |
return false; | |
} | |
/// <summary> | |
/// Advances the reader to the first child node with the provided type. | |
/// </summary> | |
/// <param name="reader">The reader.</param> | |
/// <param name="tokenType">The type of token to advance to.</param> | |
/// <returns>True if a node of that type was found.</returns> | |
public static bool AdvanceTo(this JsonTextReader reader, JsonToken tokenType) | |
{ | |
var depth = 0; | |
while (reader.Read() && depth >= 0) | |
{ | |
if (reader.TokenType == tokenType) return true; | |
switch (reader.TokenType) | |
{ | |
case JsonToken.StartObject: | |
case JsonToken.StartArray: | |
case JsonToken.StartConstructor: | |
depth++; | |
break; | |
case JsonToken.EndObject: | |
case JsonToken.EndArray: | |
case JsonToken.EndConstructor: | |
depth--; | |
break; | |
} | |
} | |
return false; | |
} | |
/// <summary> | |
/// Enumerates the direct children of the current node. | |
/// The code using this enumeration must entirely consume the current node | |
/// after each move to the next item. | |
/// If it doesn't want to do anything with the node, for example, it should | |
/// call Skip on the reader. | |
/// If the current node is an object, the method enumerates property names. | |
/// If the current node is an array, the method advances the reader each time | |
/// MoveNext is called, but enumerates null values. | |
/// If the current node is neither an object nor an array, the method skips | |
/// the node. | |
/// </summary> | |
/// <param name="reader">The reader.</param> | |
/// <returns>An enumeration of all child property names.</returns> | |
public static IEnumerable<string> Children(this JsonTextReader reader) | |
{ | |
switch(reader.TokenType) | |
{ | |
case JsonToken.StartObject: | |
while (reader.Read()) | |
{ | |
if (reader.TokenType == JsonToken.EndObject) | |
{ | |
yield break; | |
} | |
if (reader.TokenType == JsonToken.PropertyName) | |
{ | |
var propertyName = reader.Value; | |
reader.Read(); // move to the value before yielding. | |
yield return propertyName as string; | |
} | |
} | |
break; | |
case JsonToken.StartArray: | |
while (reader.Read()) | |
{ | |
if (reader.TokenType == JsonToken.EndArray) | |
{ | |
yield break; | |
} | |
yield return null; | |
} | |
break; | |
default: | |
reader.Skip(); | |
reader.Read(); | |
yield break; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment