Skip to content

Instantly share code, notes, and snippets.

@dvhthomas
Created October 4, 2009 05:43
Show Gist options
  • Select an option

  • Save dvhthomas/201175 to your computer and use it in GitHub Desktop.

Select an option

Save dvhthomas/201175 to your computer and use it in GitHub Desktop.
esri json.cs
/// <summary>
/// Parses the results of a query operation against the layer
/// in to <see cref="Feature"/>s.
/// </summary>
/// <param name="dataSourceFields">List of valid fields</param>
/// <param name="geometryType"></param>
/// <param name="json"></param>
/// <returns></returns>
/// <remarks>Because the collection of fields can vary between each layer and even
/// between query results for each layer this actually has a two phased approach to loading
/// the data. First it loads the geometries using <see cref="Newtonsoft.Json.Linq"/> methods
/// ; this is possible because the structure of geometries is constant. Then it uses
/// a <see cref="JsonTextReader"/> to rip through the rest of the JSON content parsing
/// out the fields and their values. A bit awkward but really the only way to go given
/// the mutable list of fields, field names, and field values.</remarks>
private static IList<Feature> ReadLayerQueryResults(IEnumerable<Field> dataSourceFields, EsriGeometryType geometryType, string json)
{
IList<Feature> features = null;
if (string.IsNullOrEmpty(json)) return features;
// First the geometries.
IList<IGeometry> geometries = null;
// TODO - I *think* this handles rasters and tables OK. but need to check again.
if (geometryType != EsriGeometryType.NoGeometry)
{
geometries = RestClient.BuildGeometryFromJson(geometryType, json);
if (geometries == null || geometries.Count == 0) return features;
}
var geometryIndex = 0;
// Then the attributes
JsonReader reader = new JsonTextReader(new StringReader(json));
while (reader.Read())
{
while (Convert.ToString(reader.Value) != "features")
{
reader.Read();
}
// Found feature collections
features = new List<Feature>();
while (reader.Read())
{
var feature = new Feature();
if (Convert.ToString(reader.Value) == "attributes")
{
// Found the attributes for a feature - this always comes
// before the geometry if the geometry is even present
IAttributesTable table = new AttributesTable();
reader.Read();
do
{
// As long as we're still in the attribute list...
if (reader.TokenType == JsonToken.PropertyName)
{
var fieldName = Convert.ToString(reader.Value);
reader.Read();
Field field = dataSourceFields.SingleOrDefault(f => f.Name.ToUpperInvariant() == fieldName.ToUpperInvariant());
object value = reader.Value == null
? null
: Convert.ChangeType(reader.Value, field.DataType);
if (!table.Exists(fieldName)) table.AddAttribute(fieldName, null);
table[fieldName] = value;
}
reader.Read();
} while (reader.TokenType != JsonToken.EndObject
&& Convert.ToString(reader.Value) != "attributes");
feature.Attributes = table;
if (geometries != null)
{
feature.Geometry = geometries[geometryIndex];
geometryIndex++;
}
}
// Was checking if feature null as well but a standalone table
// in an MXD being served up does not have a spatial component
// to turn in to geometries.
if (feature.Attributes == null) continue;
if (feature.Geometry != null & geometryType != EsriGeometryType.NoGeometry)
{
features.Add(feature);
}
else if (feature.Geometry == null & geometryType == EsriGeometryType.NoGeometry)
{
features.Add(feature);
}
}
}
return features;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment