Ege Ersoz
Ege Ersoz

Reputation: 6571

Extracting a key-value pair from inside a string

I have the following string:

string myString = "{'gridObject':'[1,2,3,4],[5,6,7,8]'}";

How do I process this into an object so that I can do this:

charts[0]     //=> [1,2,3,4]
charts[0][1]  //=> 2

If I can convert it to this object, even better:

public class gridObject {

    public int datarow   {get; set;}
    public int datacol   {get; set;}
    public int datasizex {get; set;}
    public int datasizey {get; set;}

}

Upvotes: 1

Views: 1277

Answers (3)

Jure
Jure

Reputation: 1176

Done with custom parsing:

public class GridObject
{
    public int datarow { get; set; }
    public int datacol { get; set; }
    public int datasizex { get; set; }
    public int datasizey { get; set; }
}

/// <summary>
/// MySuperObject class which holds a reference to inner array of integers
/// </summary>
public class MySuperObject
{
    public List<int> Items { get; set; } // Inner array of list of integers

    public MySuperObject()
    {
        Items = new List<int>();
    }

    public override string ToString()
    {
        // Need to override ToString to return something like "[1,2,3,4]"
        var result = "";
        foreach (var item in Items)
        {
            if (result.Length > 0)
                result += ",";
            result += item.ToString();
        }
        return string.Format("[{0}]", result);
    }

    /// <summary>
    /// Function to generate GridObject from existing set of integers
    /// </summary>
    public GridObject GetGridObject()
    {
        var result = new GridObject();
        if (Items.Count >= 1) result.datarow = Items[0];
        if (Items.Count >= 2) result.datacol = Items[1];
        if (Items.Count >= 3) result.datasizex = Items[2];
        if (Items.Count >= 4) result.datasizey = Items[3];
        return result;
    }
}

// Parse functions
public List<MySuperObject> Parse(string value)
{
    if (string.IsNullOrEmpty(value))
        throw new ArgumentException("value cannot be null or empty!", "value");

    var result = new List<MySuperObject>();

    // First get the indexes of first [ and last ]
    var idxStart = value.IndexOf("[");
    var idxEnd = value.LastIndexOf("]");
    // Check validity
    if (idxStart < 0 || idxEnd < 0 || idxEnd <= idxStart)
        return result; // Return empty list

    value = value.Substring(idxStart, idxEnd - idxStart + 1).Trim();

    // Split by [] after replacing spaces with empty strings (and removing first and last [ and ])
    var arr = value.Replace(" ", "").Trim('[',']').Split(new[] { "],[" }, StringSplitOptions.RemoveEmptyEntries);
    foreach (var str in arr)
    {
        // Construct list of integers with a help of LINQ
        var nums = str.Split(',').Select(t => Convert.ToInt32(t)).ToList();

        // Create and add MySuperObject to existing list which will be returned
        result.Add(new MySuperObject
        {
            Items = new List<int>(nums),
        });
    }

    return result;
}

And here is the usage of such parsing:

var myString = "{'gridObject':'[1,2,3,4],[5,6,7,8]'}";
var value = Parse(myString);
// Get all grid objects
var allGridObjects = value.Select(t => t.GetGridObject()).ToList();

Of course, this could need a little bit more of error checking but basically, this MySuperObject is used to use any number of integers you desire, while providing you with a helper method of "GetGridObject" to fill you grid object with appropriate numbers from array of numbers.

Upvotes: 0

Oguz Ozgul
Oguz Ozgul

Reputation: 7187

This is what I would do.

Create your classes first,

public class GridObject
{
    public int datarow { get; set; }
    public int datacol { get; set; }
    public int datasizex { get; set; }
    public int datasizey { get; set; }
}

public class GridObjectCollection
{
    public GridObject[] GridObjects { get; set; }
}

Then, to see what JSON you need, serialize it once: (JsonConvert is part of Json.NET, you can get it with NuGet)

GridObjectCollection gridObjects = new GridObjectCollection();
gridObjects.GridObjects = new GridObject[]
{
    new GridObject() { datacol = 1, datarow = 2, datasizex = 3, datasizey = 4 },
    new GridObject() { datacol = 5, datarow = 6, datasizex = 7, datasizey = 8 }
};

Console.WriteLine
(
    JsonConvert.SerializeObject
    (
        gridObjects,
        new JsonSerializerSettings() { Formatting = Formatting.Indented }
    )
);

Here you can see that the valid JSON content which will produce these classes when deserialized is like:

{
  "GridObjects": [
    {
      "datarow": 2,
      "datacol": 1,
      "datasizex": 3,
      "datasizey": 4
    },
    {
      "datarow": 6,
      "datacol": 5,
      "datasizex": 7,
      "datasizey": 8
    }
  ]
}

Then, just try a deserialization just to make sure:

var f = JsonConvert.DeserializeObject<GridObjectCollection>
(
    "{'GridObjects':[{'datarow':2,'datacol':1,'datasizex':3,'datasizey':4},{'datarow':6,'datacol':5,'datasizex':7,'datasizey':8}]}"
);

Upvotes: 3

Yacoub Massad
Yacoub Massad

Reputation: 27871

Here is one way to do it:

public static gridObject[] Parse(string str)
{
    int first = str.IndexOf("[");

    int last = str.LastIndexOf("]");

    str = str.Substring(first, last - first + 1);

    string[] big_parts = str.Split(new string[] {"[", "],[", "]"} , StringSplitOptions.RemoveEmptyEntries);


    return big_parts.Select(x =>
    {
        string[] small_parts = x.Split(',');

        return new gridObject()
        {
            datarow = Convert.ToInt32(small_parts[0]),
            datacol = Convert.ToInt32(small_parts[1]),
            datasizex = Convert.ToInt32(small_parts[2]),
            datasizey = Convert.ToInt32(small_parts[3]),

        };
    }).ToArray();
}

It first searches for the the first [ and the last ] and trims anything before [ and after ].

Then, it splits the string based on [, ],[, ].

This will give us 1,2,3,4 and 5,6,7,8 for your example.

Then for each one of them, we split based on , and convert the results into a gridObject object.

Upvotes: 1

Related Questions