-1

Say I have a simple POCO class:

Public Class Person

    Public Property Id As Integer

    Public Property Name As String

    Public Property Age As Integer

End Class

I would like to return a list of these objects in JSON format, but each object also needs a UUID, so using a LINQ Select statement, I create a new anoynmous types that include all properties from Person, plus the addtional UUID field. I'm wondering if there is a shorter way to create such a type. Ex:

Public Function GetPeople() As JsonResult

    Dim people = _personRepository.GetAllPeople()

    ' Shorter way to write the statement below?
    ' EG something like "people.Select(Function(x) x.Merge(New With { .uuid = Guid.NewGuid() })"

    Return Json(people.Select(Function(x) New With {
         x.Id,
         x.Name,
         x.Age,
         .uuid = Guid.NewGuid().ToString()
    }, JsonRequestBehavior.AllowGet)

 End Function

I'm fine with code examples in VB or C#

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
ryan
  • 1,451
  • 11
  • 27
  • Is it okay, that the `uuid` is comepltely volatile? Everytime you query `GetPeople` the uuid will change. If you need a guid it would be simpler, to use the `Id` property for it and it would also be constitent. – Marco Feb 08 '18 at 16:46
  • 1
    This feels like an XY problem, what are you actually trying to achieve with this? – DavidG Feb 08 '18 at 16:53
  • 1
    You could circumvent the Json() method and create the json yourself. A good serializer like Json.Net can add properties to the serialized json. Example https://stackoverflow.com/questions/18692523/how-to-add-an-extra-property-into-a-serialized-json-string-using-json-net – Ralf Feb 08 '18 at 16:58
  • 1
    It has been [discussed rather long time ago](https://stackoverflow.com/questions/587836/linq-add-property-to-results) ... :-) – thmshd Feb 08 '18 at 17:06
  • You say you have a "simple POCO Class", but are you using it with LINQ to Entities? Because, in this scenario, the Select statement is directly transformed into SQL and would lead to problems when trying to transform any expression there pointing to non-db Properties – thmshd Feb 08 '18 at 17:42

2 Answers2

2

Using JSON.net you can inject properties dynamically via the JObject .Add method.

I have then added a little static helper method to add the UID to your POCO class. This allows the addition of the dynamic property to be done inline.

An example of this -

//POCO
public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
    //Dummy repo for example
    public static class _personRepository
    {
        public static List<Person> GetAllPeople()
        {
            return new List<Person>();
        }
    }

    class Program
    {   
        //static helper class - accepts a POCO and dynamically adds a property and spits out a JObject
        private static JObject IDPerson(Person person)
        {
            var ret = JObject.FromObject(person);
            ret.Add("UID", Guid.NewGuid().ToString());
            return ret;
        }
        static void Main(string[] args)
        {
            //get the list of people

            var allpeople = _personRepository.GetAllPeople();
            //in line here select a new object from our helper method
            var qry =
                (
                    from person
                    in allpeople
                    select IDPerson(person) //this is the dynamic bit 
                ).ToList();
        }
    }
DotNetHitMan
  • 931
  • 8
  • 20
0

you can also convert your object to an expando and add any extra properties before turning it into json

var map = new Func<Person, dynamic>(person =>
{
    var result = person.ToDynamic();
    result.Uuid = Guid.NewGuid();
    return result;
});

var results = persons
    .Select(p => map(p))
    .ToList();

where .ToDynamic does what it sais :)

public static dynamic ToDynamic(this object value)
{
    IDictionary<string, object> expando = new ExpandoObject();
    var properties = TypeDescriptor.GetProperties(value.GetType());
    foreach (PropertyDescriptor property in properties)
    {
        expando.Add(property.Name, property.GetValue(value));
    }

    return expando as ExpandoObject;
}
Dan Dohotaru
  • 2,809
  • 19
  • 15