1

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!

PiotrG
  • 743
  • 6
  • 24
  • 1
    Possible duplicate of [Turn C# object into a JSON string in .NET 4](http://stackoverflow.com/questions/6201529/turn-c-sharp-object-into-a-json-string-in-net-4) – Trey May 16 '17 at 13:45

1 Answers1

2

It doesn't seem all that difficult, just generate a POCO (or set of them) the same structure as your JSON:

public class Root
{
    public ProductMeta[] meta_data { get; set; }
}

public class ProductMeta
{
    public int? id { get; set; }
    public string key { get; set; }
    public Dictionary<string, ProductPriceGroup> value { get; set; }
}

public class ProductPriceGroup
{
    public ProductGroupPrice group_price { get; set; }
}

public class ProductGroupPrice
{
    public string price { get; set; }
    public object price_type { get; set; }
}

This was my generation code:

var serObj = new Root();
serObj.meta_data = new ProductMeta[1];
serObj.meta_data[0] = new ProductMeta();
serObj.meta_data[0].id = 220910;
serObj.meta_data[0].key = "rbp_role_config";
serObj.meta_data[0].value = new Dictionary<string, ProductPriceGroup>();
serObj.meta_data[0].value.Add("customer_group_1", new ProductPriceGroup() { group_price = new ProductGroupPrice { price = "150", price_type = "currency" } });
serObj.meta_data[0].value.Add("customer_group_2", new ProductPriceGroup() { group_price = new ProductGroupPrice { price = "125", price_type = "currency" } });
var jss = new JavaScriptSerializer();
var result = jss.Serialize(serObj);
Console.WriteLine(result);

Resulting JSON (I formatted it for comparison, actual generation is a single line / no indentation/spacing):

{
  "meta_data": [
  {
    "id":220910,
    "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"
        }
      }
    }
  }]
}
Der Kommissar
  • 5,848
  • 1
  • 29
  • 43
  • Thank you! I see now where I went wrong, using a Dictionary for value did the trick! – PiotrG May 17 '17 at 05:33
  • So it turns out that I've run into a subsequent problem. The ProductMeta Class property "value" must be a string. What should I be looking at doing? Building the dictionary and then converting to a string? – PiotrG May 17 '17 at 09:30
  • @piotr.g Then your original question is *different*, I recommend you post a new question (feel free to ping me on this answer with a link to it) and I might be able to offer some advice in an hour or so. – Der Kommissar May 17 '17 at 11:17
  • Taking another look at the all the API code and documentation (this is Wordpress Woocommerce REST API), I found that the ProductMeta is defined in their API docs as having a "value" property as a string but when I fetch the data it expects an object. I think it's best if I have another crack at it without wasting your time. Unfortunatly there is no private message feature on stack else I would have messaged you directly. Thanks again! – PiotrG May 17 '17 at 13:15
  • `JavaScriptSerializer` is mostly old and slow, Microsoft, I and many others recommend to use json.net: http://www.newtonsoft.com/json – Mafii May 18 '17 at 07:08
  • Mafii, I am using Newtonsoft JSON.net, but that doesn't have anything to do with the question... – PiotrG May 18 '17 at 07:09
  • @Mafii I use `DataContractSerializer`, but that's overkill for this demonstration but that is all entirely irrelevant for this answer. – Der Kommissar May 18 '17 at 17:04
  • @EBrown Since I am relatively new to programming, would you say the code above is okay or do you see any obvious bad practices? – PiotrG May 18 '17 at 19:26