This is the output I am after:
  "key": "rbp_role_config",
  "value": {
    "customer_group_1": {
      "group_price": {
        "price": "150",
        "price_type": "currency"
      }
    },
    "customer_group_2": {
      "group_price": {
        "price": "125",
        "price_type": "currency"
      }
    }
  }
Here are my classes:
[DataContract]
public class ProductMeta
{
    /// <summary>
    /// Meta ID. 
    /// read-only
    /// </summary>
    [DataMember(EmitDefaultValue = false)]
    public int? id { get; set; }
    /// <summary>
    /// Meta key.
    /// </summary>
    [DataMember(EmitDefaultValue = false)]
    public string key { get; set; }
    /// <summary>
    /// Meta value.
    /// </summary>
    [DataMember(EmitDefaultValue = false)]
    public object value { get; set; }
}
[DataContract]
public class ProductPriceGroup
{
    /// <summary>
    /// Meta Value
    /// </summary>
    [DataMember(EmitDefaultValue = false)]
    public ProductGroupPrice group_price { get; set; }
}
[DataContract]
public class ProductGroupPrice
{
    /// <summary>
    /// Product Price
    /// </summary>
    [DataMember(EmitDefaultValue = false)]
    public string price { get; set; }
    /// <summary>
    /// Product Price Type
    /// </summary>
    [DataMember(EmitDefaultValue = false)]
    public string price_type { get; set; }
}
The values "customer_group_1", "customer_group_2", etc will be grabbed from a SQL table so they need to be dynamic properties.
Finally here is the code using the classes:
using (var connection = new SqlConnection(_connectionString))
using (var command = new SqlCommand(queryString, connection))
{
    try
    {
        connection.Open();
    }
    catch (SqlException sqlEx)
    {
        log.Error(sqlEx.Message);
        return null;
    }
    var reader = command.ExecuteReader();
    var productMetaDict = new Dictionary<string, ProductPriceGroup>();
    while (reader.Read())
    {
        try
        {
            var group = StringToSlug(reader["customerpricegroup"].ToString());
            productMetaDict.Add(group, new ProductPriceGroup() { group_price = new ProductGroupPrice { price = reader["regular_price"].ToString(), price_type = "currency" } });
        }
        catch (SqlException sqlEx)
        {
            log.Error(sqlEx.Message);
        }
   }
   if (productMetaDict.Count > 0)
   {
       var productMeta = new ProductMeta();
       productMeta.key = "rbp_role_config";
       productMeta.value = productMetaDict;
       return productMeta;
   };
I've reworked my code with some help from EBrown and now am at the point that I am returning the JSON I want but for some reason I am getting First Chance Exceptions when trying to add it to the meta data property of the Product.
For illustration purposes when converting to a string I get the following:
"key": "rbp_role_config",
"value": {
    "customer_group_1": {
        "group_price": {
            "price": "100,70",
            "price_type": "currency"
        }
    },
    "customer_group_2": {
        "group_price": {
            "price": "100,70",
            "price_type": "currency"
        }
    }
}
I have a Product class with the following property:
/// <summary>
/// Meta data. See Product - Meta data properties
/// </summary>
[DataMember(EmitDefaultValue = false)]
public List<ProductMeta> meta_data { get; set; }
When trying to add the meta data object to this list I get "A first chance exception of type 'System.NullReferenceException' occurred". "p" here is a Product object. I've checked and p is not null, productMeta is not null.
p.meta_data.Add(productMeta);
EDIT: I was rather silly and forgot to new up a List for the meta_data property...
p.meta_data = new List<ProductMeta>();
Now I don't get any First Chance Exceptions.
All Done! Thanks for the help!
 
    