-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
NEST/Elasticsearch.Net version:
2.4.4
Elasticsearch version:
2.3.3
Description of the problem including expected versus actual behavior:
When we Index any object, we normally run through the DefaultFieldNameInferrer - using that we can control the property names in ES. We've used this to fix all names to be lowercase in our project.
But when we index anything containing a JToken, the DefaultFieldNameInferrer is ignored.
Steps to reproduce:
Use the following code.
class Program
{
static void Main(string[] args)
{
ConnectionSettings settings = new ConnectionSettings(new SingleNodeConnectionPool(new Uri("http://127.0.0.1:9200/")));
settings.DefaultFieldNameInferrer(s => s.ToLower());
settings.DefaultIndex("testindex");
settings.ThrowExceptions();
ElasticClient client = new ElasticClient(settings);
var item = new MyClass { MyInteger = 5, MyString = "Hello world" };
var itemAsJtoken = JToken.FromObject(item);
client.Index(itemAsJtoken);
}
}
public class MyClass
{
public string MyString { get; set; }
public int MyInteger { get; set; }
}
Observe that the auto-created mapping on testindex is as follows:
{
"testindex" : {
"mappings" : {
"jtoken" : {
"properties" : {
"MyInteger" : {
"type" : "long"
},
"MyString" : {
"type" : "string"
}
}
}
}
}
}
If we index the item instead of itemAsJtoken, we get the following map:
{
"testindex" : {
"mappings" : {
"myclass" : {
"properties" : {
"myinteger" : {
"type" : "long"
},
"mystring" : {
"type" : "string"
}
}
}
}
}
}
Relevant sources:
We found an issue in Newtonsoft.NET, where they've changed the way the contract resolvers are called. It seems that the DefaultContractResolver in Newtonsoft no longer calls its ResolvePropertyName method, which is used internally by NEST. The issue for that is here:
JamesNK/Newtonsoft.Json/issues/950
We can reproduce this by creating the following code:
class Program
{
static void Main(string[] args)
{
var item = new MyClass { MyInteger = 5, MyString = "Hello world" };
var itemAsJtoken = JToken.FromObject(item);
var serializerSettings = new JsonSerializerSettings();
serializerSettings.ContractResolver = new MyContractResolver();
var serializer = JsonSerializer.Create(serializerSettings);
StringBuilder sb = new StringBuilder();
using (var sw = new StringWriter(sb))
serializer.Serialize(sw, itemAsJtoken);
Console.WriteLine(sb.ToString());
}
}
public class MyClass
{
public string MyString { get; set; }
public int MyInteger { get; set; }
}
internal class MyContractResolver : DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
{
return propertyName.ToLower();
}
}
Relevant people (on my end): @Genbox