Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed JsonParser #29

Merged
merged 4 commits into from
Aug 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Graphite.Test/Graphite.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<IsPackable>false</IsPackable>
<RootNamespace>ahd.Graphite.Test</RootNamespace>
<AssemblyName>ahd.Graphite.Test</AssemblyName>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\graphite.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
Expand All @@ -19,6 +21,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="System.Text.Json" Version="4.7.2" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
Expand Down
58 changes: 49 additions & 9 deletions Graphite.Test/GraphiteClientTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using ahd.Graphite.Base;
using Newtonsoft.Json;
using ahd.Graphite.Exceptions;
using Razorvine.Pickle;
using Xunit;

namespace ahd.Graphite.Test
{
public class GraphiteClientTest
Expand All @@ -24,6 +25,22 @@ public void CanCreateClient()
var client = new GraphiteClient();
}

[Fact]
[Trait("Category", "Integration")]
public async Task CanSerialiseHttpContent()
{
var json = "{\"is_leaf\": \"0\", \"name\": \"pickled\", \"path\": \"usage.unittest.pickled.\"}";
var client = new HttpClient();
var response = await client.GetAsync("http://echo.jsontest.com/is_leaf/0/name/pickled/path/usage.unittest.pickled./");
await response.EnsureSuccessStatusCodeAsync();
var read = await response.Content.ReadAsAsync<GraphiteMetric>(CancellationToken.None);
var des = JsonSerializer.Deserialize<GraphiteMetric>(json);
Assert.Equal(des.Text, read.Text);
Assert.Equal(des.Expandable, read.Expandable);
Assert.Equal(des.Id, read.Id);
Assert.Equal(des.Leaf, read.Leaf);
}

[Fact]
public void CanPickle()
{
Expand Down Expand Up @@ -296,18 +313,41 @@ public async Task CanExpandMetrics()
public void CanDeserializeMetrics()
{
var json = "{\"is_leaf\": \"0\", \"name\": \"pickled\", \"path\": \"usage.unittest.pickled.\"}";
var metric = JsonConvert.DeserializeObject<GraphiteMetric>(json);
var metric = JsonSerializer.Deserialize<GraphiteMetric>(json);
Assert.Equal("usage.unittest.pickled", metric.Id);
Assert.Equal("pickled", metric.Text);
Assert.False(metric.Leaf);
Assert.True(metric.Expandable);
}

[Fact]
public void CanDeserializeMetricDatapoint()
{
var json = "[3.5, 1474716420]";
var dp = JsonSerializer.Deserialize<MetricDatapoint>(json);
Assert.Equal(3.5D, dp.Value);
Assert.Equal(1474716420L, dp.UnixTimestamp);

json = "[null, 1474716424]";
dp = JsonSerializer.Deserialize<MetricDatapoint>(json);
Assert.Null(dp.Value);
Assert.Equal(1474716424, dp.UnixTimestamp);
}

[Fact]
public void DeserializationThrowsOnIllegalJson()
{
var json = "{Test: 24, Array: [3.5, null]}";
Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<MetricDatapoint>(json));
Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<GraphiteMetric>(json));
Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<GraphiteMetricData>(json));
}

[Fact]
public void CanDeserializeMetricsData()
{
var json = "{\"target\": \"usage.unittest.cpu.count\", \"datapoints\": [[3.5, 1474716420], [null, 1474716480], [null, 1474716540], [0, 1474716600], [7.0, 1474716660], [null, 1474716720], [null, 1474716780]]}";
var data = JsonConvert.DeserializeObject<GraphiteMetricData>(json);
var data = JsonSerializer.Deserialize<GraphiteMetricData>(json);
Assert.Equal("usage.unittest.cpu.count", data.Target);
Assert.NotNull(data.Datapoints);
Assert.Equal(7,data.Datapoints.Length);
Expand All @@ -321,16 +361,16 @@ public void CanDeserializeMetricsData()
public void CanSerialize()
{
var datapoint = new MetricDatapoint(null, 987654321);
var json = JsonConvert.SerializeObject(datapoint);
var json = JsonSerializer.Serialize(datapoint);
Assert.Equal("[null,987654321]", json);

var datapoint2 = new MetricDatapoint(5, 123456789);
json = JsonConvert.SerializeObject(datapoint2);
Assert.Equal("[5.0,123456789]", json);
json = JsonSerializer.Serialize(datapoint2);
Assert.Equal("[5,123456789]", json);

var metricData = new GraphiteMetricData("unit.test", new[] { datapoint2, datapoint });
json = JsonConvert.SerializeObject(metricData);
Assert.Equal("{\"target\":\"unit.test\",\"datapoints\":[[5.0,123456789],[null,987654321]]}", json);
json = JsonSerializer.Serialize(metricData);
Assert.Equal("{\"target\":\"unit.test\",\"datapoints\":[[5,123456789],[null,987654321]]}", json);
}

[Fact]
Expand Down
10 changes: 8 additions & 2 deletions Graphite/Graphite.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<Description>client implementation for sending and retrieving values from and to any graphite server.</Description>
<Product>Graphite</Product>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>graphite.snk</AssemblyOriginatorKeyFile>
<AssemblyOriginatorKeyFile>..\graphite.snk</AssemblyOriginatorKeyFile>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
Expand Down Expand Up @@ -54,8 +54,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="3.1.4" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Razorvine.Pickle" Version="1.0.0" />
<PackageReference Include="System.Text.Json" Version="4.7.2" />
</ItemGroup>

<ItemGroup>
Expand All @@ -77,4 +77,10 @@
</Compile>
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>ahd.Graphite.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f5a0c6d7f18a890e7c76bf85cef11fbde4769fc7f5c41f1e436245c97b6fd7c5dd4947b216c0107f56f621f396b88f5dd13aa3dc7958d99de286011beaea2ef423ed897012af252276705efe81d17268e4e09b1909985c8b65e2cc874e7c1df59178e03dfed26701d1d45f6b1d0ab467f6d753cacb3a5a2a27024284c83beecc</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

</Project>
52 changes: 50 additions & 2 deletions Graphite/GraphiteMetric.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
using System;
using Newtonsoft.Json;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace ahd.Graphite
{
/// <summary>
/// graphite metric tree node
/// </summary>
[JsonConverter(typeof(GraphiteMetricConverter))]
public class GraphiteMetric
{
/// <summary>
/// </summary>
/// <param name="path"></param>
/// <param name="is_leaf"></param>
/// <param name="name"></param>
[JsonConstructor]
public GraphiteMetric(string path, string is_leaf, string name)
{
Id = path.TrimEnd('.');
Expand Down Expand Up @@ -42,4 +43,51 @@ public GraphiteMetric(string path, string is_leaf, string name)
/// </summary>
public string Text { get; }
}

internal class GraphiteMetricConverter : JsonConverter<GraphiteMetric>
{
public override GraphiteMetric Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException($"Can not deserialize {nameof(GraphiteMetric)}");

var path = String.Empty;
var is_leaf = String.Empty;
var name = String.Empty;
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
var propertyName = reader.GetString();
reader.Read();
switch (propertyName)
{
case nameof(path):
path = reader.GetString();
break;
case nameof(is_leaf):
is_leaf = reader.GetString();
break;
case nameof(name):
name = reader.GetString();
break;
default:
throw new JsonException($"Unexpected Property Name: {propertyName}");
}
}
}

return new GraphiteMetric(path, is_leaf, name);
}

public override void Write(Utf8JsonWriter writer, GraphiteMetric value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteString("path", value.Expandable ? value.Id + "." : value.Id);
writer.WriteString("is_leaf", value.Leaf ? "1" : "0");
writer.WriteString("name", value.Text);
writer.WriteEndObject();
}
}

}
53 changes: 49 additions & 4 deletions Graphite/GraphiteMetricData.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using Newtonsoft.Json;
using System;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace ahd.Graphite
{
/// <summary>
/// Metric result
/// </summary>
[JsonConverter(typeof(GraphiteMetricConverter))]
public class GraphiteMetricData
{
/// <summary>
Expand All @@ -22,13 +24,56 @@ public GraphiteMetricData(string target, MetricDatapoint[] datapoints)
/// <summary>
/// Target name, as returned from graphite
/// </summary>
[JsonProperty("target")]
public string Target { get; }

/// <summary>
/// List of timestamped values as returned from graphite
/// </summary>
[JsonProperty("datapoints")]
public MetricDatapoint[] Datapoints { get; }

internal class GraphiteMetricConverter : JsonConverter<GraphiteMetricData>
{
public override GraphiteMetricData Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException($"Can not deserialize {nameof(GraphiteMetricData)}");
var target = string.Empty;
var datapoints = Array.Empty<MetricDatapoint>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
var propertyName = reader.GetString();
reader.Read();

switch (propertyName)
{
case nameof(target):
target = reader.GetString();
break;
case nameof(datapoints):
datapoints = JsonSerializer.Deserialize<MetricDatapoint[]>(ref reader);
break;
default:
throw new JsonException($"Unexpected Property Name: {propertyName}");
}
}
}
return new GraphiteMetricData(target,datapoints);
}

public override void Write(Utf8JsonWriter writer, GraphiteMetricData value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteString("target", value.Target);
writer.WriteStartArray("datapoints");
foreach (var datapoint in value.Datapoints)
{
JsonSerializer.Serialize(writer, datapoint, options);
}
writer.WriteEndArray();
writer.WriteEndObject();
}
}
}
}
15 changes: 3 additions & 12 deletions Graphite/HttpClientExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace ahd.Graphite
{
internal static class HttpClientExtensions
{
private static readonly JsonSerializer Serializer = new JsonSerializer();

internal static async Task<T> ReadAsAsync<T>(this HttpContent content, CancellationToken cancellationToken)
{
using (var stream = await content.ReadAsStreamAsync().ConfigureAwait(false))
{
cancellationToken.ThrowIfCancellationRequested();
using (var sReader = new StreamReader(stream))
using (var jReader = new JsonTextReader(sReader))
{
return Serializer.Deserialize<T>(jReader);
}
return await JsonSerializer.DeserializeAsync<T>(stream, cancellationToken: cancellationToken);
}
}
}
Expand Down
Loading