13

I'm working with SwiftType Elastic Search + C# and running into an issue deserializing the response due to the fact that SwiftType returns all of the fields as objects with a raw property (https://swiftype.com/documentation/app-search/api/search) for example:

{
  "meta": {
    "warnings": [],
    "page": {
      "current": 1,
      "total_pages": 1,
      "total_results": 2,
      "size": 10
    },
    "request_id": "6887a53f701a59574a0f3a7012e01aa8"
  },
  "results": [
    {
      "phone": {
        "raw": 3148304280.0
      },
      "accounts_balance_ach": {
        "raw": 27068128.71
      },
      "accounts_balance_pending": {
        "raw": "46809195.64"
      },
      "email": {
        "raw": "[email protected]"
      },
      "accounts_count": {
        "raw": 6.0
      },
      "id": {
        "raw": "c98808a2-d7d6-4444-834d-2fe4f6858f6b"
      },
      "display_name": {
        "raw": "The Johnstons"
      },
      "type": {
        "raw": "Couple"
      },
      "advisor_email": {
        "raw": "[email protected]"
      },
      "created_at": {
        "raw": "2018-10-02T10:42:07+00:00"
      },
      "source": {
        "raw": "event"
      },
      "accounts_balance": {
        "raw": 43629003.47
      },
      "accounts_donations": {
        "raw": 38012278.75
      },
      "advisor_name": {
        "raw": "Cloyd Jakubowski"
      },
      "_meta": {
        "score": 0.42934617
      }
    },
    {
      "phone": {
        "raw": 2272918612.0
      },
      "accounts_balance_ach": {
        "raw": 35721452.35
      },
      "accounts_balance_pending": {
        "raw": "35117465.2"
      },
      "email": {
        "raw": "[email protected]"
      },
      "accounts_count": {
        "raw": 1.0
      },
      "id": {
        "raw": "687af11f-0f73-4112-879c-1108303cb07a"
      },
      "display_name": {
        "raw": "Kennith Johnston"
      },
      "type": {
        "raw": "Individual"
      },
      "advisor_email": {
        "raw": "[email protected]"
      },
      "created_at": {
        "raw": "2018-10-02T16:16:02+00:00"
      },
      "source": {
        "raw": "website"
      },
      "accounts_balance": {
        "raw": 23063874.19
      },
      "accounts_donations": {
        "raw": 33025175.79
      },
      "advisor_name": {
        "raw": "Ernie Mertz"
      },
      "_meta": {
        "score": 0.39096162
      }
    }
  ]
}

I need to map each key to its value, eg results[0].email = "[email protected]";

I saw a promising option with custom converters but I want to make sure there is not a more dynamic way to do this before I take the verbose approach.

2

3 Answers 3

16

I would suggest using the JsonPathConverter class found in Can I specify a path in an attribute to map a property in my class to a child property in my JSON?. This will allow you to declare a strongly-typed Result class and then easily map each of the properties to the value of the respective raw child value in the JSON without having to declare a ton of awkward single-property classes.

Declare your model as shown below. Note that the Result class needs a [JsonConverter] attribute on it to tie it to the JsonPathConverter (otherwise the property paths will not work and you will get default values in your properties).

public class RootObject
{
    public List<Result> results { get; set; }
}

[JsonConverter(typeof(JsonPathConverter))]
public class Result
{
    [JsonProperty("phone.raw")]
    public string Phone { get; set; }

    [JsonProperty("accounts_balance_ach.raw")]
    public decimal AccountsBalanceAch { get; set; }

    [JsonProperty("accounts_balance_pending.raw")]
    public decimal AccountsBalancePending { get; set; }

    [JsonProperty("email.raw")]
    public string Email { get; set; }

    [JsonProperty("accounts_count.raw")]
    public decimal AccountsCount { get; set; }

    [JsonProperty("id.raw")]
    public string Id { get; set; }

    [JsonProperty("display_name.raw")]
    public string DisplayName { get; set; }

    [JsonProperty("type.raw")]
    public string Type { get; set; }

    [JsonProperty("advisor_email.raw")]
    public string AdvisorEmail { get; set; }

    [JsonProperty("created_at.raw")]
    public string CreatedAt { get; set; }

    [JsonProperty("source.raw")]
    public string Source { get; set; }

    [JsonProperty("accounts_balance.raw")]
    public decimal AccountsBalance { get; set; }

    [JsonProperty("accounts_donations.raw")]
    public decimal AccountsDonations { get; set; }

    [JsonProperty("advisor_name.raw")]
    public string AdvisorName { get; set; }

    [JsonProperty("_meta.score")]
    public decimal MetaScore { get; set; }
}

Then you can just deserialize as usual:

var root = JsonConvert.DeserializeObject<RootObject>(json);

Here is a working demo: https://dotnetfiddle.net/wYxwIF

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

2 Comments

most expressive and usefull +1
This is exactly what I was looking for! +1
4

The Most dynamic way for you would be to use The Newtonsoft JObejct class.

It will parse your JSON string into a JSON object for you to use, this is if you do not have a corresponding model and you need to create a dynamic JSON object.

For example:

string json = "{
  "meta": {
    "warnings": [],
    "page": {
      "current": 1,
      "total_pages": 1,
      "total_results": 2,
      "size": 10
    },
    "request_id": "6887a53f701a59574a0f3a7012e01aa8"
  },
  "results": [
    {
      "phone": {
        "raw": 3148304280.0
      },
      "accounts_balance_ach": {
        "raw": 27068128.71
      },
      "accounts_balance_pending": {
        "raw": "46809195.64"
      },
      "email": {
        "raw": "[email protected]"
      },
      "accounts_count": {
        "raw": 6.0
      },
      "id": {
        "raw": "c98808a2-d7d6-4444-834d-2fe4f6858f6b"
      },
      "display_name": {
        "raw": "The Johnstons"
      },
      "type": {
        "raw": "Couple"
      },
      "advisor_email": {
        "raw": "[email protected]"
      },
      "created_at": {
        "raw": "2018-10-02T10:42:07+00:00"
      },
      "source": {
        "raw": "event"
      },
      "accounts_balance": {
        "raw": 43629003.47
      },
      "accounts_donations": {
        "raw": 38012278.75
      },
      "advisor_name": {
        "raw": "Cloyd Jakubowski"
      },
      "_meta": {
        "score": 0.42934617
      }
    },
    {
      "phone": {
        "raw": 2272918612.0
      },
      "accounts_balance_ach": {
        "raw": 35721452.35
      },
      "accounts_balance_pending": {
        "raw": "35117465.2"
      },
      "email": {
        "raw": "[email protected]"
      },
      "accounts_count": {
        "raw": 1.0
      },
      "id": {
        "raw": "687af11f-0f73-4112-879c-1108303cb07a"
      },
      "display_name": {
        "raw": "Kennith Johnston"
      },
      "type": {
        "raw": "Individual"
      },
      "advisor_email": {
        "raw": "[email protected]"
      },
      "created_at": {
        "raw": "2018-10-02T16:16:02+00:00"
      },
      "source": {
        "raw": "website"
      },
      "accounts_balance": {
        "raw": 23063874.19
      },
      "accounts_donations": {
        "raw": 33025175.79
      },
      "advisor_name": {
        "raw": "Ernie Mertz"
      },
      "_meta": {
        "score": 0.39096162
      }
    }
  ]
}"

JObject result = JObject.Parse(json);

result is now a JSON object and you can access it's properties.

Comments

1

You can use the following link to convert json to C# class. Then can use Newtonsoft Json to parse:

var jsonMessage = "{ \"meta\": {  \"warnings\": [],  \"page\": {   \"current\": 1,   \"total_pages\": 1,   \"total_results\": 2,   \"size\": 10  },  \"request_id\": \"6887a53f701a59574a0f3a7012e01aa8\" }, \"results\": [{   \"phone\": {    \"raw\": 3148304280.0   },   \"accounts_balance_ach\": {    \"raw\": 27068128.71   },   \"accounts_balance_pending\": {    \"raw\": \"46809195.64\"   },   \"email\": {    \"raw\": \"[email protected]\"   },   \"accounts_count\": {    \"raw\": 6.0   },   \"id\": {    \"raw\": \"c98808a2-d7d6-4444-834d-2fe4f6858f6b\"   },   \"display_name\": {    \"raw\": \"The Johnstons\"   },   \"type\": {    \"raw\": \"Couple\"   },   \"advisor_email\": {    \"raw\": \"[email protected]\"   },   \"created_at\": {    \"raw\": \"2018-10-02T10:42:07+00:00\"   },   \"source\": {    \"raw\": \"event\"   },   \"accounts_balance\": {    \"raw\": 43629003.47   },   \"accounts_donations\": {    \"raw\": 38012278.75   },   \"advisor_name\": {    \"raw\": \"Cloyd Jakubowski\"   },   \"_meta\": {    \"score\": 0.42934617   }  },  {   \"phone\": {    \"raw\": 2272918612.0   },   \"accounts_balance_ach\": {    \"raw\": 35721452.35   },   \"accounts_balance_pending\": {    \"raw\": \"35117465.2\"   },   \"email\": {    \"raw\": \"[email protected]\"   },   \"accounts_count\": {    \"raw\": 1.0   },   \"id\": {    \"raw\": \"687af11f-0f73-4112-879c-1108303cb07a\"   },   \"display_name\": {    \"raw\": \"Kennith Johnston\"   },   \"type\": {    \"raw\": \"Individual\"   },   \"advisor_email\": {    \"raw\": \"[email protected]\"   },   \"created_at\": {    \"raw\": \"2018-10-02T16:16:02+00:00\"   },   \"source\": {    \"raw\": \"website\"   },   \"accounts_balance\": {    \"raw\": 23063874.19   },   \"accounts_donations\": {    \"raw\": 33025175.79   },   \"advisor_name\": {    \"raw\": \"Ernie Mertz\"   },   \"_meta\": {    \"score\": 0.39096162   }  } ]}";

var message = JsonConvert.DeserializeObject<RootObject>(jsonMessage);
Console.WriteLine(message.meta.page.current); // prints 1

public class Page
{
    public int current { get; set; }
    public int total_pages { get; set; }
    public int total_results { get; set; }
    public int size { get; set; }
}

public class Meta
{
    public List<object> warnings { get; set; }
    public Page page { get; set; }
    public string request_id { get; set; }
}

public class Phone
{
    public double raw { get; set; }
}

public class AccountsBalanceAch
{
    public double raw { get; set; }
}

public class AccountsBalancePending
{
    public string raw { get; set; }
}

public class Email
{
    public string raw { get; set; }
}

public class AccountsCount
{
    public double raw { get; set; }
}

public class Id
{
    public string raw { get; set; }
}

public class DisplayName
{
    public string raw { get; set; }
}

public class Type
{
    public string raw { get; set; }
}

public class AdvisorEmail
{
    public string raw { get; set; }
}

public class CreatedAt
{
    public DateTime raw { get; set; }
}

public class Source
{
    public string raw { get; set; }
}

public class AccountsBalance
{
    public double raw { get; set; }
}

public class AccountsDonations
{
    public double raw { get; set; }
}

public class AdvisorName
{
    public string raw { get; set; }
}

public class Meta2
{
    public double score { get; set; }
}

public class Result
{
    public Phone phone { get; set; }
    public AccountsBalanceAch accounts_balance_ach { get; set; }
    public AccountsBalancePending accounts_balance_pending { get; set; }
    public Email email { get; set; }
    public AccountsCount accounts_count { get; set; }
    public Id id { get; set; }
    public DisplayName display_name { get; set; }
    public Type type { get; set; }
    public AdvisorEmail advisor_email { get; set; }
    public CreatedAt created_at { get; set; }
    public Source source { get; set; }
    public AccountsBalance accounts_balance { get; set; }
    public AccountsDonations accounts_donations { get; set; }
    public AdvisorName advisor_name { get; set; }
    public Meta2 _meta { get; set; }
}

public class RootObject
{
    public Meta meta { get; set; }
    public List<Result> results { get; set; }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.