src/common/details/helpers/json_helpers.cs (430 lines of code) (raw):
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
//
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text.Json;
namespace Azure.AI.Details.Common.CLI
{
public static class JsonElementHelpers
{
public static string GetPropertyStringOrEmpty(this JsonDocument document, string name)
{
return document.RootElement.GetPropertyStringOrEmpty(name);
}
public static string GetPropertyStringOrEmpty(this JsonElement element, string name)
{
if (element.ValueKind == JsonValueKind.Object && element.TryGetProperty(name, out var value))
{
return value.ValueKind == JsonValueKind.String
? value.GetString() ?? string.Empty
: value.GetRawText();
}
return string.Empty;
}
public static string? GetPropertyStringOrNull(this JsonDocument document, string name)
{
return document.RootElement.GetPropertyStringOrNull(name);
}
public static string? GetPropertyStringOrNull(this JsonElement element, string name)
{
if (element.ValueKind == JsonValueKind.Object && element.TryGetProperty(name, out var value))
{
return value.ValueKind == JsonValueKind.String
? value.GetString()
: value.GetRawText();
}
return null;
}
public static bool GetPropertyBool(this JsonDocument document, string name, bool defaultValue)
{
return document.RootElement.GetPropertyBool(name, defaultValue);
}
public static bool GetPropertyBool(this JsonElement element, string name, bool defaultValue)
{
if (element.ValueKind == JsonValueKind.Object && element.TryGetProperty(name, out var value))
{
return value.ValueKind == JsonValueKind.True || value.ValueKind == JsonValueKind.False
? value.GetBoolean()
: defaultValue;
}
return defaultValue;
}
public static JsonElement? GetPropertyElementOrNull(this JsonDocument document, string name)
{
return document.RootElement.GetPropertyElementOrNull(name);
}
public static JsonElement? GetPropertyElementOrNull(this JsonElement element, string name)
{
return element.ValueKind == JsonValueKind.Object && element.TryGetProperty(name, out var value)
? value
: null;
}
public static JsonElement.ArrayEnumerator? GetPropertyArrayOrNull(this JsonDocument document, string name)
{
return document.RootElement.GetPropertyArrayOrNull(name);
}
public static JsonElement.ArrayEnumerator? GetPropertyArrayOrNull(this JsonElement element, string name)
{
return element.ValueKind == JsonValueKind.Object && element.TryGetProperty(name, out var value)
? value.EnumerateArray()
: null;
}
public static JsonElement[] GetPropertyArrayOrEmpty(this JsonDocument document, string name)
{
return document.RootElement.GetPropertyArrayOrEmpty(name);
}
public static JsonElement[] GetPropertyArrayOrEmpty(this JsonElement element, string name)
{
return element.GetPropertyArrayOrNull(name)?.ToArray() ?? Array.Empty<JsonElement>();
}
}
public class JsonHelpers
{
#region make member
public static string MakeMember(string name, string json)
{
return $"\"{name}\":{json}";
}
public static string MakeMemberOrEmpty(string name, string json)
{
return !string.IsNullOrEmpty(json)
? MakeMember(name, json)
: "";
}
public static string ContinueWithMemberOrEmpty(string name, string json)
{
return StringHelpers.PrependOrEmpty(",", MakeMemberOrEmpty(name, json));
}
#endregion
#region make string
public static string MakeString(string value)
{
return $"\"{value}\"";
}
public static string MakeString(INamedValues values, string valueName)
{
var value = values.GetOrEmpty(valueName);
return MakeString(value);
}
public static string MakeStringOrEmpty(string value)
{
return !string.IsNullOrEmpty(value)
? MakeString(value)
: "";
}
public static string MakeStringOrEmpty(INamedValues values, string valueName)
{
var value = values.GetOrEmpty(valueName);
return MakeStringOrEmpty(value);
}
#endregion
#region make string array
public static string MakeStringArray(string delimitedValues, string delimiters)
{
string csv = MakeNotEmptyStringsCsv(delimitedValues, delimiters);
return $"[{csv}]";
}
public static string MakeStringArray(INamedValues values, string delimitedValuesName, string delimiters)
{
var delimitedValues = values.GetOrEmpty(delimitedValuesName);
return MakeStringArray(delimitedValues, delimiters);
}
public static string MakeStringArray(INamedValues values, string singleValueName, string delimitedValuesName, string delimiters)
{
var singleValue = values.GetOrEmpty(singleValueName);
var delimitedValues = values.GetOrEmpty(delimitedValuesName);
return MakeStringArray($"{singleValue};{delimitedValues}", delimiters);
}
public static string MakeStringArrayOrEmpty(string delimitedValues, string delimiters)
{
string csv = MakeNotEmptyStringsCsv(delimitedValues, delimiters);
return !string.IsNullOrEmpty(csv)
? $"[{csv}]"
: "";
}
public static string MakeStringArrayOrEmpty(INamedValues values, string delimitedValuesName, string delimiters)
{
var delimitedValues = values.GetOrEmpty(delimitedValuesName);
return MakeStringArrayOrEmpty(delimitedValues, delimiters);
}
public static string MakeStringArrayOrEmpty(INamedValues values, string singleValueName, string delimitedValuesName, string delimiters)
{
var singleValue = values.GetOrEmpty(singleValueName);
var delimitedValues = values.GetOrEmpty(delimitedValuesName);
var singleOk = !string.IsNullOrEmpty(singleValue);
var delimitedOk = !string.IsNullOrEmpty(delimitedValues);
delimitedValues = singleOk && delimitedOk
? $"{singleValue};{delimitedValues}"
: delimitedOk
? delimitedValues
: singleValue;
return MakeStringArrayOrEmpty(delimitedValues, delimiters);
}
#endregion
#region make string member
public static string MakeStringMember(string name, string value)
{
return MakeMember(name, MakeString(value));
}
public static string MakeStringMember(string name, INamedValues values, string valueName)
{
return MakeStringMember(name, MakeString(values, valueName));
}
public static string MakeStringMemberOrEmpty(string name, string value)
{
return MakeMemberOrEmpty(name, MakeStringOrEmpty(value));
}
public static string MakeStringMemberOrEmpty(string name, INamedValues values, string valueName)
{
return MakeMemberOrEmpty(name, MakeStringOrEmpty(values, valueName));
}
public static string ContinueWithStringMemberOrEmpty(string name, string value)
{
return StringHelpers.PrependOrEmpty(",", MakeStringMemberOrEmpty(name, value));
}
public static string ContinueWithStringMemberOrEmpty(string name, INamedValues values, string valueName)
{
return StringHelpers.PrependOrEmpty(",", MakeStringMemberOrEmpty(name, values, valueName));
}
#endregion
#region make string array member
public static string MakeStringArrayMember(string name, string delimitedValues, string delimiters)
{
return MakeMember(name, MakeStringArray(delimitedValues, delimiters));
}
public static string MakeStringArrayMember(string name, INamedValues values, string delimitedValuesName, string delimiters)
{
return MakeMember(name, MakeStringArray(values, delimitedValuesName, delimiters));
}
public static string MakeStringArrayMember(string name, INamedValues values, string singleValueName, string multipleValueName, string delimiters)
{
string jsonArray = MakeStringArray(values, singleValueName, multipleValueName, delimiters);
return MakeMember(name, jsonArray);
}
public static string MakeStringArrayMemberOrEmpty(string name, string delimitedValues, string delimiters)
{
return MakeMemberOrEmpty(name, MakeStringArrayOrEmpty(delimitedValues, delimiters));
}
public static string MakeStringArrayMemberOrEmpty(string name, INamedValues values, string delimitedValuesName, string delimiters)
{
return MakeMemberOrEmpty(name, MakeStringArrayOrEmpty(values, delimitedValuesName, delimiters));
}
public static string MakeStringArrayMemberOrEmpty(string name, INamedValues values, string singleValueName, string multipleValueName, string delimiters)
{
string jsonArray = MakeStringArrayOrEmpty(values, singleValueName, multipleValueName, delimiters);
return MakeMemberOrEmpty(name, jsonArray);
}
public static string ContinueWithStringArrayMemberOrEmpty(string name, string delimitedValues, string delimiters)
{
return StringHelpers.PrependOrEmpty(",", MakeStringArrayMemberOrEmpty(name, delimitedValues, delimiters));
}
public static string ContinueWithStringArrayMemberOrEmpty(string name, INamedValues values, string delimitedValuesName, string delimiters)
{
return StringHelpers.PrependOrEmpty(",", MakeStringArrayMemberOrEmpty(name, values, delimitedValuesName, delimiters));
}
public static string ContinueWithStringArrayMemberOrEmpty(string name, INamedValues values, string singleValueName, string multipleValueName, string delimiters)
{
return StringHelpers.PrependOrEmpty(",", MakeStringArrayMemberOrEmpty(name, values, singleValueName, multipleValueName, delimiters));
}
#endregion
public static void PrintJson(string? text, string indent = " ", bool naked = false)
{
if (!string.IsNullOrWhiteSpace(text))
{
PrintJson(JsonDocument.Parse(text).RootElement, indent, naked);
}
}
private static void PrintJson(JsonElement element, string indent = " ", bool naked = false)
{
var print = !naked
? element.GetRawText()
: element.GetRawText()
.Replace(" \"", " ")
.Replace("\": \"", ": ")
.Replace("\": ", ": ")
.Replace("\",\r", "\r")
.Replace(",\r", "\r")
.Replace("\"\r", "\r");
Console.WriteLine(indent + print.Replace("\n", "\n" + indent) + "\n");
}
private static string MakeNotEmptyStringsCsv(string delimitedValues, string delimiters)
{
var sb = new StringBuilder();
var array = delimitedValues.Split(delimiters.ToCharArray()).ToList();
foreach (var item in array)
{
if (!string.IsNullOrEmpty(item))
{
sb.Append(MakeString(item));
sb.Append(", ");
}
}
return sb.ToString().Trim(',', ' ');
}
public static string MergeJsonObjects(JsonElement elem1, params JsonElement[] parameters)
{
var allPages = new List<JsonElement> { elem1 };
allPages.AddRange(parameters);
return MergeJsonObjects(allPages);
}
public static string MergeJsonObjects(List<JsonElement> allPages)
{
var properties = new Dictionary<string, string>();
foreach (var page in allPages)
{
foreach (var property in page.EnumerateObject())
{
if (!properties.ContainsKey(property.Name))
{
properties.Add(property.Name, property.Value.GetRawText());
}
else if (property.Value.ValueKind == JsonValueKind.Array)
{
properties[property.Name] = MergeJsonArrays(properties[property.Name], property.Value.GetRawText());
}
else
{
properties[property.Name] = property.Value.GetRawText();
}
}
}
// return as json object
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions{ Indented = false });
writer.WriteStartObject();
foreach (var property in properties)
{
writer.WritePropertyName(property.Key);
writer.WriteRawValue(property.Value);
}
writer.WriteEndObject();
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
private static string MergeJsonArrays(string v1, string v2)
{
var array1 = JsonDocument.Parse(v1).RootElement.EnumerateArray().ToList();
var array2 = JsonDocument.Parse(v2).RootElement.EnumerateArray().ToList();
array1.AddRange(array2);
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions{ Indented = false });
writer.WriteStartArray();
foreach (var item in array1)
{
item.WriteTo(writer);
}
writer.WriteEndArray();
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
public static string GetJsonObjectText(Dictionary<string, string> properties)
{
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions{ Indented = false });
WriteJsonObject(writer, properties);
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
public static string GetJsonObjectText(Dictionary<string, List<string>> properties)
{
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions{ Indented = false });
WriteJsonObject(writer, properties);
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
public static string GetJsonArrayText(List<Dictionary<string, string>> list)
{
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions{ Indented = false });
WriteJsonArray(writer, list);
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
public static List<Dictionary<string, string>> FromJsonArrayText(string json)
{
var list = new List<Dictionary<string, string>>();
using var doc = JsonDocument.Parse(json);
foreach (var item in doc.RootElement.EnumerateArray())
{
var properties = new Dictionary<string, string>();
foreach (var property in item.EnumerateObject())
{
properties.Add(property.Name, property.Value.GetString() ?? property.Value.GetRawText());
}
list.Add(properties);
}
return list;
}
private static void WriteJsonArray(Utf8JsonWriter writer, List<Dictionary<string, string>> items)
{
writer.WriteStartArray();
foreach (var item in items.Where(x => x != null).ToList())
{
WriteJsonObject(writer, item);
}
writer.WriteEndArray();
}
private static void WriteJsonObject(Utf8JsonWriter writer, Dictionary<string, string> properties)
{
writer.WriteStartObject();
foreach (var key in properties.Keys)
{
WritePropertyJsonOrString(writer, key, properties[key]);
}
writer.WriteEndObject();
}
private static void WritePropertyJsonOrString(Utf8JsonWriter writer, string key, string value)
{
if (key.EndsWith(".json"))
{
if (!string.IsNullOrWhiteSpace(value))
{
writer.WritePropertyName(key);
writer.WriteRawValue(value);
}
}
else
{
writer.WriteString(key, value);
}
}
private static void WriteJsonOrStringValue(Utf8JsonWriter writer, string key, string value)
{
if (key.EndsWith(".json"))
{
if (!string.IsNullOrWhiteSpace(value))
{
writer.WriteRawValue(value);
}
}
else
{
writer.WriteStringValue(value);
}
}
private static void WriteJsonObject(Utf8JsonWriter writer, Dictionary<string, List<string>> properties)
{
writer.WriteStartObject();
foreach (var key in properties.Keys)
{
var values = properties[key].Where(x => !string.IsNullOrEmpty(x));
if (values.Count() == 1)
{
WritePropertyJsonOrString(writer, key, values.First());
continue;
}
writer.WriteStartArray(key);
foreach (var item in values)
{
WriteJsonOrStringValue(writer, key, item);
}
writer.WriteEndArray();
}
writer.WriteEndObject();
}
}
}