1

The API I am working with requires JSON data, but also requires that the data be sent in the Content-Type of `application/x-www-form-urlencoded' so I am deserializing to a dictionary to pass the body to FormUrlEncodedContent. Everything was reasonably well with the world until I had to send a body that wasn't a flat structure.

I was reading the answer here, and thought that I had stumbled upon the solution to my problem, but I'm getting the following error:

Error reading string. Unexpected token: StartObject. Path 'filters[0]', line 1, position 165.

I am reasonably sure before I tried this method, the position was position 164, so at least I've made some progress before falling on my hands and knees here.

Here's an example of what I am doing.

Objects:

public partial class SearchRequest
{
    [JsonProperty("id")]
    public string Id { get; set; }

    JsonProperty("fieldId")]
    public string FieldId { get; set; }

    [JsonProperty("fields")]
    public string[] Fields { get; set; }

    [JsonProperty("filters")]
    public Filter[] Filters { get; set; }

    [JsonProperty("pageNumber")]
    public long PageNumber { get; set; }

    [JsonProperty("searchText")]
    public string SearchText { get; set; }

    [JsonProperty("sorting")]
    public Sorting[] Sorting { get; set; }

    [JsonProperty("promptValues")]
    public PromptValue[] PromptValues { get; set; }
}

public class Filter
{
    [JsonProperty("fieldId")]
    public string FieldId { get; set; }

    [JsonProperty("operator")]
    public string Operator { get; set; }

    [JsonProperty("value")]
    public string Value { get; set; }
}

public class PromptValue
{
    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("collectionValue")]
    public string CollectionValue { get; set; }

    [JsonProperty("promptId")]
    public string PromptId { get; set; }

    [JsonProperty("value")]
    public Value Value { get; set; }
}

public class Value
{
}

public class Sorting
{
    [JsonProperty("fieldId")]
    public string FieldId { get; set; }

    [JsonProperty("direction")]
    public long Direction { get; set; }
}

Method:

Dictionary<string, string> dictBody;
SearchRequest searchRequest = new SearchRequest
{
    // Do stuff
}
string body = Serialize.ToJson(searchRequest);
var jObj = JObject.Parse(body);
jObj["filters"] = JsonConvert.SerializeObject(jObj["filters"].ToObject<string[]>());  // Problem encountered here.
jObj["sorting"] = JsonConvert.SerializeObject(jObj["sorting"].ToObject<string[]>());
jObj["promptValues"] = JsonConvert.SerializeObject(jObj["promptValues"].ToObject<string[]>());
dictBody = JsonConvert.DeserializeObject<Dictionary<string, string>>(jObj.ToString());

JSON Sample:

{
    "id": "blah",
    "fieldId": "blah",
    "fields": [
        "blah"
    ],
    "filters": [
        {
            "fieldId": "blah",
            "operator": "eq",
            "value": "blah"
        },
        {
            "fieldId": "blah",
            "operator": "eq",
            "value": "blah"
        }
    ],
    "pageNumber": "blah",
    "searchText": "blah",
    "sorting": [
        {
            "fieldId": "blah",
            "direction": "eq"
        }
    ],
    "promptValues": [
        {
            "id": "blah",
            "collectionValue": "blah",
            "promptId": "blah",
            "value": {}
        }
    ]
}

Can someone help? Even better, is there way of automatically recognising the embedded objects and flattening them?

7
  • 2
    Can you share the sample JSON you are trying to deserialize? Commented Sep 11, 2019 at 8:34
  • Added a JSON sample as requested)) Commented Sep 11, 2019 at 8:43
  • 1
    Did you try c# Build URL encoded query from model object for HttpClient? Commented Sep 11, 2019 at 9:53
  • 1
    Well it's an extension method so you would do var dictBody = searchRequest.ToKeyValue(); Commented Sep 11, 2019 at 10:09
  • 1
    Thanks @dbc works perfectly. Appreciate your patience with the additional question. I'd be happy to accept this as an answer if you want to post it below. Commented Sep 11, 2019 at 10:43

1 Answer 1

3

I've tested your case and came up with the following solution:

The code below should come after your SearchRequest class.

SearchRequest searchRequest = new SearchRequest
{
    // Do stuff
}

When you have your class, you do the follwing:

Dictionary<string, string> dictBody = new Dictionary<string, string>();

var properties = searchRequest.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var prop in properties)
{
    var valueAsObj = prop.GetValue(searchRequest);
    var valueAsString = JsonConvert.SerializeObject(valueAsObj);
    dictBody.Add(prop.Name, valueAsString);
}

This will fill your Dictionary<string, string>. Here is an example:
enter image description here

Hope this helps, Cheers :)

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for providing an answer. I really appreciate that you tested it too. I've upvoted, but already found a working solution from the comments above.
Hey, thanks for the positive answer. :) Upvoted as well

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.