using Edge.Core.Processor.Dispatcher.Attributes; using Edge.Core.Processor.Dispatcher; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Reflection; using System.Text; using System.Text.Json.Serialization; using System.Text.Json; using System.Threading.Tasks; using System.Xml.Linq; using Edge.Core.UniversalApi; using Edge.Core.Processor.Communicator; using Newtonsoft.Json.Schema.Generation; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Schema; namespace Edge.Core.Processor { public enum ProcessorType { /// /// used to communciator with a device, must have a communicator underlying. /// DeviceProcessor, /// /// /// Application } public class ProcessorDescriptor { public IProcessor Processor { get; } /// /// Gets the type of the Processor /// public ProcessorType ProcessorType { get; } /// /// will be the DeviceHandler instance if processor type is Device Processor. /// will be the AppProcessor instance if processor type is IAppProcessor. /// public object DeviceHandlerOrApp { get; } /// /// Gets all the methodInfo for functions marked with UnversalApi attribute. /// public IEnumerable UniversalApiInfos { get; } /// /// will be null if processor is type AppProcessor. /// public object DeviceProcessorContext { get; } /// /// will be null if processor is type Application. /// public object DeviceProcessorCommunicator { get; } public ProcessorDescriptor(IProcessor processor, ProcessorType processorType, object deviceHandlerOrApp, IEnumerable universalApiInfos, object deviceProcessorContext, object deviceProcessorCommunicator) { this.Processor = processor; this.ProcessorType = processorType; this.DeviceProcessorContext = deviceProcessorContext; this.DeviceProcessorCommunicator = deviceProcessorCommunicator; this.DeviceHandlerOrApp = deviceHandlerOrApp; this.UniversalApiInfos = universalApiInfos; } } public class UniversalEventInfo { public UniversalEventInfo(string eventName, Type eventDataType) { this.EventName = eventName; this.EventDataType = eventDataType; } public string EventName { get; private set; } public Type EventDataType { get; private set; } } public class UniversalApiInfo { public IProcessor Processor { get; set; } public UniversalApiInfo(MethodInfo serviceApiInfo, UniversalApiAttribute apiAttribute) { this.ServiceApiInfo = serviceApiInfo; this.ApiAttribute = apiAttribute; } public UniversalApiInfo(PropertyInfo propertyApiInfo, UniversalApiAttribute apiAttribute) { this.PropertyApiInfo = propertyApiInfo; this.ApiAttribute = apiAttribute; } public UniversalApiInfo(UniversalEventInfo eventApiInfo, UniversalApiAttribute apiAttribute) { this.EventApiInfo = eventApiInfo; this.ApiAttribute = apiAttribute; } /// /// public MethodInfo ServiceApiInfo { get; private set; } public PropertyInfo PropertyApiInfo { get; private set; } public UniversalEventInfo EventApiInfo { get; private set; } /// /// public UniversalApiAttribute ApiAttribute { get; private set; } } public class UniversalApiInfoDoc { /// /// the DeviceHanlder or AppProcessor type full name string. /// public string ProviderType { get; set; } public string[] ProviderTags { get; set; } /// /// Name of the MetaConfig that instantiate the processor instance. /// public string ProviderConfigName { get; set; } /// /// like Service, Property, Event /// public string BaseCategory { get; set; } /// /// The Service function name, or Property name, or Event name. /// public string ApiName { get; set; } /// /// The unique string that used to locate the specific API endpoint in a Processor. /// public string Path { get; set; } public string InputParametersExampleJson { get; set; } /// /// /// public string[] InputParametersJsonSchemaStrings { get; set; } public string OutputParametersExampleJson { get; set; } public string OutputParametersJsonSchema { get; set; } public string Description { get; set; } } public static class ExtensionMethods { /// /// Get the ProcessorDescriptor for a processor. /// /// /// ProcessorDescriptor public static ProcessorDescriptor ProcessorDescriptor(this IProcessor processor) { if (processor == null) throw new ArgumentNullException(nameof(processor)); if (processor is IAppProcessor application) { var apiInfos = GetUniversalApiInfos(application.GetType(), processor); return new ProcessorDescriptor(processor, ProcessorType.Application, processor, apiInfos, null, null); } else { dynamic p = processor; var deviceProcessorHandler = p.Context.Handler; Type handlerType = deviceProcessorHandler.GetType(); var methodInfos = GetUniversalApiInfos(handlerType, processor); return new ProcessorDescriptor(processor, ProcessorType.DeviceProcessor, deviceProcessorHandler, methodInfos, p.Context, p.Context.Communicator); } } private static IEnumerable GetUniversalApiInfos(Type handlerOrAppType, IProcessor processor) { var serviceUniversalApiInfos = handlerOrAppType.GetMethods() .Where(m => m.CustomAttributes != null && m.CustomAttributes.Any(a => a.AttributeType .IsAssignableFrom(typeof(UniversalApiAttribute))) && m.GetCustomAttribute().IgnoreApi == false && typeof(Task).IsAssignableFrom(m.ReturnType)) .Select(mi => new UniversalApiInfo(mi, mi.GetCustomAttributes().First()) { Processor = processor }); var eventUniversalApiAttributes = handlerOrAppType .GetCustomAttributes().Where(att => att.IgnoreApi == false); if (eventUniversalApiAttributes.Any() && eventUniversalApiAttributes.GroupBy(g => g.Name).Any(g => g.Count() >= 2)) throw new ArgumentOutOfRangeException("Multiple event UniversalApiAttributes with same Name: " + (eventUniversalApiAttributes.GroupBy(g => g.Name).Where(g => g.Count() >= 2).First().Key ?? "") + " declared on type: " + handlerOrAppType.FullName + ", make sure the event name is unique on this type."); var eventUniversalApiInfos = eventUniversalApiAttributes.Select(atti => new UniversalApiInfo(new UniversalEventInfo(atti.Name, atti.EventDataType), atti) { Processor = processor }); var propertyUniversalApiInfos = handlerOrAppType.GetProperties() .Where(p => p.CustomAttributes != null && p.CustomAttributes.Any(a => a.AttributeType .IsAssignableFrom(typeof(UniversalApiAttribute))) && p.GetCustomAttribute().IgnoreApi == false) .Select(p => new UniversalApiInfo(p, p.GetCustomAttributes().First()) { Processor = processor }); var apiInfos = serviceUniversalApiInfos.Concat(eventUniversalApiInfos).Concat(propertyUniversalApiInfos); return apiInfos; } /// /// Filtering endpoint(either DeviceHandler or AppProcessor) from processors, and find those matched with its type Assignable for T. /// /// /// /// processors that satisfy condition. public static IEnumerable WithHandlerOrApp(this IEnumerable processors) where T : class { if (processors == null) throw new ArgumentNullException(nameof(processors)); return processors.Where(p => p.IsWithHandlerOrApp()); } /// /// Determine the endpoint(either DeviceHandler or AppProcessor) from target processor satisfies its type Assignable for T. /// /// /// /// public static bool IsWithHandlerOrApp(this IProcessor processor) where T : class { if (processor == null) throw new ArgumentNullException(nameof(processor)); var endpointType = processor.ProcessorDescriptor()?.DeviceHandlerOrApp?.GetType(); if (endpointType == null) return false; return endpointType.IsAssignableFrom(typeof(T)) || typeof(T).IsAssignableFrom(endpointType); } /// /// Cast the DeviceHandler or AppProcessor to type T from the processors. /// /// the type that will cast the DeviceHandler or AppProcessor to /// /// DeviceHandlers or AppProcessors that casted to type T. public static IEnumerable SelectHandlerOrAppThenCast(this IEnumerable processors) where T : class { if (processors == null) throw new ArgumentNullException(nameof(processors)); return processors.Select(p => p.SelectHandlerOrAppThenCast()); } /// /// Cast the DeviceHandler or AppProcessor to type T from the processor. /// /// the type that will cast the DeviceHandler or AppProcessor to /// /// DeviceHandler or AppProcessor that casted to type T. public static T SelectHandlerOrAppThenCast(this IProcessor processor) where T : class { if (processor == null) throw new ArgumentNullException(nameof(processor)); var casted = processor.ProcessorDescriptor().DeviceHandlerOrApp as T; if (casted == null) throw new InvalidCastException(); return casted; } public static IEnumerable WithAttributeOrAll(this IEnumerable methodsOrCtors) where T : Attribute { var memberInfoWithAttri = methodsOrCtors.Where(mi => mi.GetCustomAttribute() != null); if (memberInfoWithAttri.Any()) return memberInfoWithAttri; return methodsOrCtors; } public static IEnumerable FilterByTags(this IEnumerable source, string[] tags) { if (source == null) throw new ArgumentNullException(nameof(source)); if (tags == null || !tags.Any() || tags.All(t => string.IsNullOrEmpty(t))) return source; else { return source.Where(d => d.ProviderTags != null && d.ProviderTags.Any()).Where(doc => tags.Intersect(doc.ProviderTags).Any()); //var filtered = new List(); //foreach (var doc in source.Where(d => d.ProviderTags != null && d.ProviderTags.Any())) //{ // if (doc.ProviderTags.Any(dt => tags.Contains(dt))) // filtered.Add(doc); //} //return filtered; } } public static IEnumerable ExtractProcessorMetaDescriptor( this IEnumerable targetEndPointTypes, bool includeSystemInternalComponent = false) { var descriptors = new List(); foreach (var endPointType in targetEndPointTypes) { var endpointTypeMetaPartsDescriptor = endPointType.GetCustomAttributes().FirstOrDefault(); if ((endpointTypeMetaPartsDescriptor?.IsSystemInternalComponent ?? false) && !includeSystemInternalComponent) continue; var pmcDescriptor = new ProcessorMetaDescriptor { //Type = endPointType.GetInterfaces().Any(ti => ti.Name == typeof(IDeviceHandler<,>).Name) ? // ProcessorTypeEnum.DeviceProcessor : ProcessorTypeEnum.AppProcessor, Type = endPointType.GetInterfaces().Any(ti => ti.Name == typeof(IAppProcessor).Name) ? ProcessorTypeEnum.AppProcessor : ProcessorTypeEnum.DeviceProcessor, SourceEndpointFullTypeStr = endPointType.AssemblyQualifiedName, Tags = endpointTypeMetaPartsDescriptor?.Tags, DisplayName = endpointTypeMetaPartsDescriptor?.DisplayName, Description = endpointTypeMetaPartsDescriptor?.Description }; if (pmcDescriptor.Type == ProcessorTypeEnum.AppProcessor) { /*App only has one Parts*/ pmcDescriptor.MetaPartsGroupDescriptors = new List() { new ProcessorMetaPartsGroupDescriptor() { GroupType = ProcessorMetaPartsTypeEnum.App, MetaPartsDescriptors = new List() { new ProcessorMetaPartsDescriptor() { FullTypeString = endPointType.AssemblyQualifiedName, TypeString = endPointType.FullName, DisplayName = endPointType.GetCustomAttribute()?.DisplayName, Description = endPointType.GetCustomAttribute()?.Description, ParametersJsonSchemaStrings = endPointType.GetConstructors().WithAttributeOrAll().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(), } } } }; } else { var groupDescriptors = new List(); var deviceHandlerGroupDescriptor = new ProcessorMetaPartsGroupDescriptor() { GroupType = ProcessorMetaPartsTypeEnum.DeviceHandler, MetaPartsDescriptors = new List() { new ProcessorMetaPartsDescriptor() { FullTypeString = endPointType.AssemblyQualifiedName, TypeString = endPointType.FullName, DisplayName = endPointType.GetCustomAttribute()?.DisplayName, Description = endPointType.GetCustomAttribute()?.Description, ParametersJsonSchemaStrings = endPointType.GetConstructors().WithAttributeOrAll().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(), } } }; groupDescriptors.Add(deviceHandlerGroupDescriptor); var metaPartsRequiredAttributes = endPointType.GetCustomAttributes(); var communicatorMetaPartsRequiredAttributes = metaPartsRequiredAttributes?.Where(at => at.RequiredPartsType?.GetInterfaces().Any(i => i.Name == typeof(ICommunicator<,>).Name) ?? false); if (communicatorMetaPartsRequiredAttributes == null || !communicatorMetaPartsRequiredAttributes.Any()) { var communicatorGroupDescriptor = new ProcessorMetaPartsGroupDescriptor() { GroupType = ProcessorMetaPartsTypeEnum.Communicator, MetaPartsDescriptors = new List(){ new ProcessorMetaPartsDescriptor() { FullTypeString = typeof(ComPortCommunicator<>).AssemblyQualifiedName, TypeString = typeof(ComPortCommunicator<>).FullName, DisplayName = typeof(ComPortCommunicator<>).GetCustomAttribute()?.DisplayName, Description = typeof(ComPortCommunicator<>).GetCustomAttribute()?.Description, ParametersJsonSchemaStrings = typeof(ComPortCommunicator<>).GetConstructors().WithAttributeOrAll().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(), }, new ProcessorMetaPartsDescriptor() { FullTypeString = typeof(TcpClientCommunicator<>).AssemblyQualifiedName, TypeString = typeof(TcpClientCommunicator<>).FullName, DisplayName = typeof(TcpClientCommunicator<>).GetCustomAttribute()?.DisplayName, Description = typeof(TcpClientCommunicator<>).GetCustomAttribute()?.Description, ParametersJsonSchemaStrings = typeof(TcpClientCommunicator<>).GetConstructors().WithAttributeOrAll().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(), } } }; groupDescriptors.Add(communicatorGroupDescriptor); } else { groupDescriptors.Add(new ProcessorMetaPartsGroupDescriptor() { GroupType = ProcessorMetaPartsTypeEnum.Communicator, MetaPartsDescriptors = communicatorMetaPartsRequiredAttributes.Select(att => new ProcessorMetaPartsDescriptor() { FullTypeString = att.RequiredPartsType.AssemblyQualifiedName, TypeString = att.RequiredPartsType.FullName, DisplayName = att.RequiredPartsType.GetCustomAttribute()?.DisplayName, Description = att.RequiredPartsType.GetCustomAttribute()?.Description, ParametersJsonSchemaStrings = att.RequiredPartsType.GetConstructors().WithAttributeOrAll().Select(ctor => ctor.ResolveParamsJsonSchemas()).ToList(), }).ToArray() }); } var deviceProcessorMetaPartsRequiredAttri = metaPartsRequiredAttributes?.FirstOrDefault(at => at.RequiredPartsType?.GetInterfaces().Any(i => i.Name == typeof(IDeviceProcessor<,>).Name) ?? false); if (deviceProcessorMetaPartsRequiredAttri != null) { var specifiedProcessorGroupDescriptor = new ProcessorMetaPartsGroupDescriptor() { GroupType = ProcessorMetaPartsTypeEnum.DeviceProcessor, MetaPartsDescriptors = new List(){ new ProcessorMetaPartsDescriptor() { FullTypeString = deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.AssemblyQualifiedName, TypeString = deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.FullName, DisplayName = deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.GetCustomAttribute()?.DisplayName, Description = deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.GetCustomAttribute()?.Description, ParametersJsonSchemaStrings = deviceProcessorMetaPartsRequiredAttri.RequiredPartsType.GetConstructors().WithAttributeOrAll().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(), } } }; groupDescriptors.Add(specifiedProcessorGroupDescriptor); } else { var processorGroupDescriptor = new ProcessorMetaPartsGroupDescriptor() { GroupType = ProcessorMetaPartsTypeEnum.DeviceProcessor, MetaPartsDescriptors = new List(){ new ProcessorMetaPartsDescriptor() { FullTypeString = typeof(GenericDeviceProcessor<,>).AssemblyQualifiedName, TypeString= typeof(GenericDeviceProcessor<,>).FullName, DisplayName = typeof(GenericDeviceProcessor<,>).GetCustomAttribute()?.DisplayName, Description = typeof(GenericDeviceProcessor<,>).GetCustomAttribute()?.Description, ParametersJsonSchemaStrings = typeof(GenericDeviceProcessor<,>).GetConstructors().WithAttributeOrAll().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(), }, new ProcessorMetaPartsDescriptor() { FullTypeString = typeof(HalfDuplexActivePollingDeviceProcessor<,>).AssemblyQualifiedName, TypeString= typeof(HalfDuplexActivePollingDeviceProcessor<,>).FullName, DisplayName = typeof(HalfDuplexActivePollingDeviceProcessor<,>).GetCustomAttribute()?.DisplayName, Description = typeof(HalfDuplexActivePollingDeviceProcessor<,>).GetCustomAttribute()?.Description, ParametersJsonSchemaStrings = typeof(HalfDuplexActivePollingDeviceProcessor<,>).GetConstructors().WithAttributeOrAll().Select(ctor=>ctor.ResolveParamsJsonSchemas()).ToList(), } } }; groupDescriptors.Add(processorGroupDescriptor); } pmcDescriptor.MetaPartsGroupDescriptors = groupDescriptors; } descriptors.Add(pmcDescriptor); } return descriptors; } /// /// call the fallback config resolve method from target metaparts type. /// /// /// return true for called the method and updated the ParametersJsonArrayStr successfully, /// false indicates no fallback config resolve method defined, and no update. public static bool TryCallMetaPartsConfigCompatibilityMethodAndUpdate(this ProcessorMetaPartsConfig metaPartsConfig) { var metaPartsType = Type.GetType(metaPartsConfig.FullTypeString);// ObjectInstanceCreator.CurrentDomainProcessorEndPointTypes; if (metaPartsType == null) return false;// throw new ArgumentException("Could not find any metaPartsType that has type full name to: " + metaPartsConfig.FullTypeString); string methodName = "ResolveCtorMetaPartsConfigCompatibility"; var resolveCompatibleMethodInfo = metaPartsType.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) .Where(mi => mi.Name == methodName && mi.ReturnType == typeof(List)).FirstOrDefault(); if (resolveCompatibleMethodInfo == null) { // no resolve method defined in metaParts type, unable to resolve. return false; } else { try { var reformatParams = resolveCompatibleMethodInfo.Invoke(null, new object[] { metaPartsConfig.ParametersJsonArrayStr } ) as List; var jsonSerializerOptions = new JsonSerializerOptions() { WriteIndented = true, PropertyNameCaseInsensitive = true, }; jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); var reformatParamsStr = "[" + reformatParams.Select(p => JsonSerializer.Serialize(p)).Aggregate((acc, n) => acc + ", " + n) + "]"; metaPartsConfig.ParametersJsonArrayStr = reformatParamsStr; return true; } catch { return false; } } } public static List ResolveParamsJsonSchemas(this MethodBase methodOrCtor) { Type declaringType = methodOrCtor.DeclaringType; var apiDesc = methodOrCtor.GetCustomAttribute(); if (apiDesc != null) { if (!string.IsNullOrEmpty(apiDesc.SchemaEmbededResourceName)) { var resourceName = declaringType.Assembly.GetManifestResourceNames().FirstOrDefault(n => n.EndsWith("." + apiDesc.SchemaEmbededResourceName)); if (resourceName != null) { var resourceStream = declaringType.Assembly.GetManifestResourceStream(resourceName); if (resourceStream != null) using (var sr = new StreamReader(resourceStream)) { var content = sr.ReadToEnd(); try { var jsonSchemaRootElement = JsonDocument.Parse(content).RootElement; if (jsonSchemaRootElement.ValueKind == JsonValueKind.Array) return jsonSchemaRootElement.EnumerateArray().Select(jse => jse.GetRawText()).ToList(); return new List() { content }; } catch (Exception exxx) { } } } } if (apiDesc.SchemaStrings != null && apiDesc.SchemaStrings.Any() && apiDesc.SchemaStrings.Length == methodOrCtor.GetParameters().Where(p => !p.ParameterType.IsInterface && !p.ParameterType.IsAbstract).Count()) return apiDesc.SchemaStrings.ToList(); } var generator = new JSchemaGenerator(); generator.GenerationProviders.Add(new StringEnumGenerationProvider()); return methodOrCtor.GetParameters().Where(p => !p.ParameterType.IsInterface && !p.ParameterType.IsAbstract) .Select(p => { int serializeDepth = 0; if (IsTypeDepthTooHighForSerialize(p.ParameterType, ref serializeDepth)) return "{}".Insert(1, "\"title\": \"" + p.Name + " ----> of type: " + p.ParameterType.Name + " 's Depth is Too High for Serialize and Generate Json Sample, try avoid recursive properties\", \"type\": \"object\""); else return generator.Generate(p.ParameterType).ToString().Insert(1, "\"title\": \"" + p.Name + "\","); }).ToList(); } /// /// Test the target type for if its serialize depth excceed 64. /// /// /// must set to 0 when call the method /// true indicates this type is invalid for json serialize. private static bool IsTypeDepthTooHighForSerialize(Type targetType, ref int depth) { var targetProperties = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.PropertyType.IsClass && !p.PropertyType.IsPrimitive); foreach (var p in targetProperties) { depth++; if (depth >= 64) return true; if (IsTypeDepthTooHighForSerialize(p.PropertyType, ref depth)) return true; else continue; } return false; } public static string ResolveParamsJsonSchemas(this PropertyInfo propertyInfo) { Type declaringType = propertyInfo.PropertyType;//.DeclaringType; var generator = new JSchemaGenerator(); generator.GenerationProviders.Add(new StringEnumGenerationProvider()); return generator.Generate(declaringType).ToString();//.Insert(1, "\"title\": \"" + propertyInfo.Name + "\","); } public static string ResolveParamsJsonSchema(this Type type) { var generator = new JSchemaGenerator(); generator.GenerationProviders.Add(new StringEnumGenerationProvider()); return generator.Generate(type).ToString(); } /// /// Generate a random Json sample based on json schema /// /// /// a random Json sample public static JToken GenerateJsonSample(this JSchema schema) { JToken output; switch (schema.Type) { case JSchemaType.Object: var jObject = new JObject(); if (schema.Properties != null) { foreach (var prop in schema.Properties) { jObject.Add(LowerCaseFirstChar(prop.Key), GenerateJsonSample(prop.Value)); } } output = jObject; break; case JSchemaType.Object | JSchemaType.Null: var jObject2 = new JObject(); if (schema.Properties != null) { foreach (var prop in schema.Properties) { jObject2.Add(LowerCaseFirstChar(prop.Key), GenerateJsonSample(prop.Value)); } } output = jObject2; break; case JSchemaType.Array: var jArray = new JArray(); foreach (var item in schema.Items) { jArray.Add(GenerateJsonSample(item)); } output = jArray; break; case JSchemaType.Array | JSchemaType.Null: var jArray2 = new JArray(); foreach (var item in schema.Items) { jArray2.Add(GenerateJsonSample(item)); } output = jArray2; break; case JSchemaType.String: if (schema.Format == "date-time") output = new JValue("2020-04-01T00:01:02.8514872+08:00"); else if (schema.Enum != null && schema.Enum.Any()) { if (string.IsNullOrEmpty(schema.Enum.First().ToString())) { if (schema.Enum.Count >= 2) output = new JValue(schema.Enum[1].ToString()); else output = Newtonsoft.Json.Linq.JValue.CreateNull(); } else output = new JValue(schema.Enum.First().ToString()); } else output = new JValue("string_sample"); break; case JSchemaType.String | JSchemaType.Null: if (schema.Format == "date-time") output = new JValue("2020-04-01T00:01:02.8514872+08:00"); else if (schema.Enum != null && schema.Enum.Any()) { if (string.IsNullOrEmpty(schema.Enum.First().ToString())) { if (schema.Enum.Count >= 2) output = new JValue(schema.Enum[1].ToString()); else output = JValue.CreateNull(); } else output = new JValue(schema.Enum.First().ToString()); } else output = new JValue("nullable_string_sample"); break; case JSchemaType.Number: output = new JValue(1.0); break; case JSchemaType.Integer: output = new JValue(1); break; case JSchemaType.Boolean: output = new JValue(false); break; case JSchemaType.Null: output = JValue.CreateNull(); break; // it's a type of object case Newtonsoft.Json.Schema.JSchemaType.String | Newtonsoft.Json.Schema.JSchemaType.Number | Newtonsoft.Json.Schema.JSchemaType.Integer | Newtonsoft.Json.Schema.JSchemaType.Boolean | Newtonsoft.Json.Schema.JSchemaType.Object | Newtonsoft.Json.Schema.JSchemaType.Array: output = JValue.CreateNull(); break; default: output = null; break; } return output; } private static string LowerCaseFirstChar(string name) { return name.Substring(0, 1).ToLower() + name.Substring(1); } public static string GenerateParametersJsonSample(this string[] parametersJsonSchemaStrings) { if (parametersJsonSchemaStrings == null || !parametersJsonSchemaStrings.Any()) return "[]"; var jTokens = parametersJsonSchemaStrings.Select(s => JSchema.Parse(s)).Select(js => js.GenerateJsonSample()); return "[" + jTokens.Select(jt => jt.Type == JTokenType.String ? "\"" + jt.ToString() + "\"" : jt.ToString()).Aggregate((acc, n) => acc + ", " + n) + "]"; } public static string GenerateParameterJsonSample(this string parameterJsonSchemaString) { if (string.IsNullOrEmpty(parameterJsonSchemaString)) return ""; var jToken = JSchema.Parse(parameterJsonSchemaString).GenerateJsonSample(); return jToken.ToString(); } } }