Skip to content

Instantly share code, notes, and snippets.

@klesouza
Created February 28, 2019 11:10
Show Gist options
  • Save klesouza/ab02e50748c0bbab14bb0d648b4dfc96 to your computer and use it in GitHub Desktop.
Save klesouza/ab02e50748c0bbab14bb0d648b4dfc96 to your computer and use it in GitHub Desktop.
C# script to generate BigQuery (BQ) schema from a C# class
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Linq;
using Travix.AirFareDomain;
using System.Collections;
using Newtonsoft.Json;
using System.IO;
namespace bq_schema_gen_dotnet
{
public class SearchResult<TCriteria, TResponse>
{
public TCriteria SearchCriteria { get; set; }
public TResponse Response { get; set; }
}
public class schema{
public string name { get; set; }
public string type { get; set; }
public string mode { get; set; }
public schema[] fields { get; set; }
}
public class test{
public string test1 { get; set; }
public int? test2 { get; set; }
public decimal[] test3 { get; set; }
public List<Point> test4 { get; set; }
public DateTime? test5 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var sc = new List<schema>();
var t = typeof(SearchResult<AirShopRequest, AirShopResponse>);
// var t = typeof(test);
var enums = new Dictionary<string, Dictionary<int, string>>();
string enumMappingHandler(Type type){
if(!enums.ContainsKey(type.FullName))
enums.Add(type.FullName, Enum.GetValues(type).Cast<int>().ToDictionary(x => x,x => Enum.GetName(type, x)));
return "INTEGER";
}
foreach(var pi in t.GetProperties()){
sc.Add(GetSchema(pi, enumMappingHandler));
}
File.WriteAllText("schema.json", JsonConvert.SerializeObject(sc,new JsonSerializerSettings{
NullValueHandling = NullValueHandling.Ignore
}));
File.WriteAllText("enum-mapping.json", JsonConvert.SerializeObject(enums,new JsonSerializerSettings{
NullValueHandling = NullValueHandling.Ignore
}));
Console.WriteLine("Hello World!");
}
public static schema GetSchema(PropertyInfo pi, Func<Type, string> enumMappingHandler)
{
var schema = new schema();
var atype = pi.PropertyType;
schema.name = pi.Name;
if(pi.PropertyType.IsArray){
schema.mode = "REPEATED";
atype = pi.PropertyType.GetElementType();
}
else if(atype.IsGenericType && typeof(IEnumerable).IsAssignableFrom(atype)){
schema.mode = "REPEATED";
atype = pi.PropertyType.GenericTypeArguments[0];
}
if(typeIn(atype, typeof(string))){
schema.type = "STRING";
}
else if(atype.IsEnum){
schema.type = enumMappingHandler(atype);
}
else if(typeIn(atype, typeof(int), typeof(int?))){
schema.type = "INTEGER";
}
else if(typeIn(atype, typeof(decimal), typeof(decimal?), typeof(float), typeof(float?))){
schema.type = "FLOAT";
}
else if(typeIn(atype, typeof(bool), typeof(bool?))){
schema.type = "BOOLEAN";
}
else if(typeIn(atype, typeof(DateTime), typeof(DateTime?))){
schema.type = "TIMESTAMP";
} else {
schema.type = "RECORD";
schema.fields = atype.GetProperties().Select(x => GetSchema(x, enumMappingHandler)).ToArray();
}
return schema;
}
private static bool typeIn(Type t, params Type[] types){
return types.Contains(t);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment