You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel.Qdrant/Services/QdrantJsonConverter.cs

174 lines
7.6 KiB

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZeroLevel.Qdrant.DataAttributes;
using ZeroLevel.Qdrant.Models;
using ZeroLevel.Services.ObjectMapping;
using ZeroLevel.Services.Reflection;
using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Qdrant.Services
{
public static class QdrantJsonConverter<T>
{
private static string KeywordToString(IMemberInfo member, object v)
{
var text = TypeHelpers.IsString(member.ClrType) ? v as string : v.ToString();
if (string.IsNullOrEmpty(text))
{
return "null";
}
else
{
return $"\"{JsonEscaper.EscapeString(text)}\"";
}
}
/*
integer - 64-bit integer in the range -9223372036854775808 to 9223372036854775807. array of long
float - 64-bit floating point number. array of double
keyword - string value. array of strings
geo - Geographical coordinates. Example: { "lon": 52.5200, "lat": 13.4050 } array of lon&lat of double
*/
private const string KYEWORD_TYPE = "keyword";
private const string GEO_TYPE = "geo";
private const string FLOAT_TYPE = "float";
private const string INTEGER_TYPE = "integer";
public static string ConvertToJson(float[] vector)
{
return "[" + string.Join(", ", vector.Select(f => f.ConvertToString())) + "]";
}
public static string ConvertToJson(T value)
{
var json = new StringBuilder();
var map = TypeMapper.Create<T>();
foreach (var member in map.Members)
{
var val = member.Getter(value);
var type = KYEWORD_TYPE;
var attributes = member.Original.GetCustomAttributes(typeof(QdrantAttribute), true);
if (attributes != null && attributes.Any())
{
var dataAttribute = attributes[0];
if (dataAttribute is KeywordAttribute)
{
type = KYEWORD_TYPE;
}
else if (dataAttribute is FloatAttribute)
{
type = FLOAT_TYPE;
}
else if (dataAttribute is IntegerAttribute)
{
type = INTEGER_TYPE;
}
else if (dataAttribute is GeoAttribute)
{
type = GEO_TYPE;
}
}
else
{
var item_type = member.ClrType;
// autodetect type
if (TypeHelpers.IsArray(item_type))
{
item_type = item_type.GetElementType();
}
else if (TypeHelpers.IsEnumerable(item_type))
{
item_type = TypeHelpers.GetElementTypeOfEnumerable(item_type);
}
if (item_type == typeof(float) || item_type == typeof(double) || item_type == typeof(decimal))
{
type = FLOAT_TYPE;
}
else if (item_type == typeof(int) || item_type == typeof(long) || item_type == typeof(byte) ||
item_type == typeof(short) || item_type == typeof(uint) || item_type == typeof(ulong) ||
item_type == typeof(ushort))
{
type = INTEGER_TYPE;
}
else if (item_type == typeof(Location))
{
type = GEO_TYPE;
}
}
switch (type)
{
case KYEWORD_TYPE:
if (TypeHelpers.IsEnumerable(member.ClrType) && TypeHelpers.IsString(member.ClrType) == false)
{
var arr = val as IEnumerable;
json.Append($"\"{member.Name.ToLowerInvariant()}\": {{ \"type\": \"keyword\", \"value\": [ {string.Join(", ", E(arr).Select(v => KeywordToString(member, v)))}] }},");
}
else
{
json.Append($"\"{member.Name.ToLowerInvariant()}\": {{ \"type\": \"keyword\", \"value\":{KeywordToString(member, val)} }},");
}
break;
case GEO_TYPE:
if (TypeHelpers.IsEnumerable(member.ClrType) && TypeHelpers.IsString(member.ClrType) == false)
{
var arr = val as IEnumerable;
json.Append($"\"{member.Name.ToLowerInvariant()}\": {{ \"type\": \"geo\", \"value\": [ {string.Join(",", E(arr).Select(v => v as Location).Where(l => l != null).Select(l => $" {{ \"lon\":{l.lon.ConvertToString()}, \"lat\":{l.lat.ConvertToString()} }}"))}] }},");
}
else
{
Location l = val as Location;
if (l != null)
{
json.Append($"\"{member.Name.ToLowerInvariant()}\": {{ \"type\": \"geo\", \"value\": {{ \"lon\":{l.lon.ConvertToString()}, \"lat\":{l.lat.ConvertToString()} }} }},");
}
}
break;
case FLOAT_TYPE:
if (TypeHelpers.IsEnumerable(member.ClrType) && TypeHelpers.IsString(member.ClrType) == false)
{
var arr = val as IEnumerable;
json.Append($"\"{member.Name.ToLowerInvariant()}\": {{ \"type\": \"float\", \"value\": [ {string.Join(",", E(arr).Select(v => Convert.ToDouble(v).ConvertToString()))}] }},");
}
else
{
json.Append($"\"{member.Name.ToLowerInvariant()}\": {{ \"type\": \"float\", \"value\": {Convert.ToDouble(val).ConvertToString()} }},");
}
break;
case INTEGER_TYPE:
if (TypeHelpers.IsEnumerable(member.ClrType) && TypeHelpers.IsString(member.ClrType) == false)
{
var arr = val as IEnumerable;
json.Append($"\"{member.Name.ToLowerInvariant()}\": {{ \"type\": \"integer\", \"value\": [ {string.Join(",", E(arr).Select(v => Convert.ToInt64(v)))}] }},");
}
else
{
json.Append($"\"{member.Name.ToLowerInvariant()}\": {{ \"type\": \"integer\", \"value\": {Convert.ToInt64(val)} }},");
}
break;
}
}
if (json[json.Length - 1] == ',')
{
json.Remove(json.Length - 1, 1);
}
return json.ToString();
}
private static IEnumerable<object> E(IEnumerable e)
{
if (e != null)
{
foreach (var i in e)
{
yield return i;
}
}
}
}
}

Powered by TurnKey Linux.