# NEST 6 QueryContainer JSON serialization

**URL:** <https://discuss.elastic.co/t/nest-6-querycontainer-json-serialization/179873>\
**Category:** Elasticsearch\
**Created:** [May 7, 2019, 2:52am UTC](https://discuss.elastic.co/t/nest-6-querycontainer-json-serialization/179873 "2019-05-07T02:52:42Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![keithpeck](https://avatars.discourse-cdn.com/v4/letter/k/a3d4f5/32.png) [@keithpeck](https://discuss.elastic.co/u/keithpeck)\
**Post date:** [May 7, 2019, 2:52am UTC](https://discuss.elastic.co/t/nest-6-querycontainer-json-serialization/179873/1 "2019-05-07T02:52:42Z")

</div>

Our entity classes have a QueryContainer property on them which we use for storing percolate queries. Serialization of ElasticSearch request/response works fine, but when the object is then returned from our API controller as JSON the QueryContainer property is an empty object: {}

```
public class Person
{
    public string Id { get; set; }
    public QueryContainer Query { get; set; }
}

// Returns correct nested container
var response = client.GetAsync(new DocumentPath<Person>("1").GetAwaiter().GetResult();

// Results in "{}"
var query = JsonConvert.SerializeObject(response.Source.Query);

```

I have read this document [https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/custom-serialization.html](https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/custom-serialization.html) and have added the NEST.JsonNetSerializer with the JsonNetSerializer.Default but this does not fix it.

I can't see a way for the property to be serialized in the model without the model being injected the ElasticSearch client and using something like client.SourceSerializer.SerializeToString

---

<div class="post-metadata">

**Author:** ![forloop](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/forloop/32/9021_2.png) [@forloop](https://discuss.elastic.co/u/forloop)\
**Post date:** [May 7, 2019, 5:40am UTC](https://discuss.elastic.co/t/nest-6-querycontainer-json-serialization/179873/2 "2019-05-07T05:40:28Z")

</div>

In this instance, `JsonConvert` would have to know how to deserialize a `QueryContainer`. Since `QueryContainer` is handled specially by an internal deserialization method however, `JsonConvert` won't know about this and will simply emit an empty JSON object.

One way that you can have `response.Source.Query` serialized correctly is to use the client's serializer and the `SerializeToString` extension method on `ElasticsearchSerializerExtensions` in `Elasticsearch.Net`

```auto
string json = client.RequestResponseSerializer.SerializeToString(response.Source.Query);

```

---

<div class="post-metadata">

**Author:** ![keithpeck](https://avatars.discourse-cdn.com/v4/letter/k/a3d4f5/32.png) [@keithpeck](https://discuss.elastic.co/u/keithpeck)\
**Post date:** [May 7, 2019, 5:49am UTC](https://discuss.elastic.co/t/nest-6-querycontainer-json-serialization/179873/3 "2019-05-07T05:49:39Z")

</div>

I was hoping that method could be avoided but thanks for confirming Russ.

---

<div class="post-metadata">

**Author:** ![forloop](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/forloop/32/9021_2.png) [@forloop](https://discuss.elastic.co/u/forloop)\
**Post date:** [May 7, 2019, 8:34am UTC](https://discuss.elastic.co/t/nest-6-querycontainer-json-serialization/179873/4 "2019-05-07T08:34:36Z")

</div>

An alternative approach would be to

1. make the `GetAsync()` call with the low level client available through `client.LowLevel`, and return a `StringResponse`
2. deserialize the response to a `JObject` with `JsonConvert.DeserializeObject<JObject>(json)`
3. serialize just the `"query"` property of the `JObject` with `JsonConvert.SerializeObject()`

For points 2 and 3, you may want to use another Json reader, like [Utf8JsonReader](https://docs.microsoft.com/en-us/dotnet/api/system.text.json.utf8jsonreader?view=netcore-3.0), if possible in your application.

---

<div class="post-metadata">

**Author:** ![keithpeck](https://avatars.discourse-cdn.com/v4/letter/k/a3d4f5/32.png) [@keithpeck](https://discuss.elastic.co/u/keithpeck)\
**Post date:** [May 7, 2019, 9:06pm UTC](https://discuss.elastic.co/t/nest-6-querycontainer-json-serialization/179873/5 "2019-05-07T21:06:59Z")

</div>

I ended up creating a JsonConverter with an in-memory client as it was the cleanest way of updating our existing code.

`  
public class QueryContainerJsonConverter : JsonConverter  
{  
// Converter should as added as global setting converter, not attribute on property.

```
    private static ElasticClient client = new ElasticClient(new ConnectionSettings(new SingleNodeConnectionPool(new Uri("http://localhost:9200")), new InMemoryConnection(), sourceSerializer: JsonNetSerializer.Default));

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(QueryContainer);
    }

    public override bool CanWrite => true;

    public override bool CanRead => false;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var queryContainer = JToken.Parse(client.SourceSerializer.SerializeToString(value));

        queryContainer.WriteTo(writer);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
            // Not needed in our use case but could use sourceSerializer.Deserialize(typeof(QueryContainer), stream);
 
             throw new NotImplementedException();
    }
}`
```

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [June 4, 2019, 9:07pm UTC](https://discuss.elastic.co/t/nest-6-querycontainer-json-serialization/179873/6 "2019-06-04T21:07:04Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
