web-dev-qa-db-fra.com

Comment amorcer des données NetTopologySuite.Geometries.Point à partir d'un fichier Json dans le noyau ASP.Net

Je veux amorcer des données "Emplacement" pour mon objet utilisateur à partir de mon fichier d'origine

L'objet c #, où Point est un NetTopologySuite.Geometries.Point fait partie de mon objet utilisateur

  public class User: IdentityUser<int> {
      // member data here
      public Point Location { get; set; } // has lat/lng data points
  }

J'amorce des données sur ma base de données au démarrage en faisant quelque chose comme ça

public void SeedUsers()
{
    if (!_userManager.Users.Any())
    {
        var userData = System.IO.File.ReadAllText("Data/UserSeedData.json");
        var users = JsonConvert.DeserializeObject<List<User>>(userData);

        var roles = new List<Role>
        {
            new Role{Name = "Member"},
            new Role{Name = "Admin"},
            new Role{Name = "Moderator"},
            new Role{Name = "VIP"},
        };

        foreach (var role in roles)
        {
            _roleManager.CreateAsync(role).Wait();
        }

        foreach (var user in users)
        {
            user.Photos.SingleOrDefault().IsApproved = true;
            _userManager.CreateAsync(user, "password").Wait();
            _userManager.AddToRoleAsync(user, "Member").Wait();
        }
     }
 }

avec un fichier json "UserSeedData.json" de tableaux json comme celui-ci et je veux pouvoir y coller une sorte de données "Localisation" qui est représentative des points de données lng/lat.

{
  "Email": "[email protected]",
  "Username": "Lola",
  "Gender": "female",
  "DateOfBirth": "1994-02-21",
  "Password": "password",
  "Created": "2017-08-02",
  "LastActive": "2017-08-02",
  "Introduction": "blah blah blah",
  "LookingFor": "blah blah blah",
  "City": "San Francisco",
  "Country": "United States",
  "Longitude": -122.431297,
  "Latitude": 37.773972,
  "Location": // something here!!!
  "Photos": [{
    "url": "https://randomuser.me/api/portraits/women/3.jpg",
    "isMain": true,
    "description": "Non deserunt labore sunt ex laboris et adipisicing ullamco officia minim."
  }]
}

Maintenant, je sais que dans ma méthode de départ, je pourrais faire quelque chose comme ça, mais je cherche un moyen de l'inclure dans mon fichier .json, afin que je puisse utiliser différents points de données

foreach (var user in users)
{
    user.Photos.SingleOrDefault().IsApproved = true;
    user.Location = new Point(-122.4194155, 37.7749295) { SRID = 4326 };
    _userManager.CreateAsync(user, "password").Wait();
    _userManager.AddToRoleAsync(user, "Member").Wait();
}
6
user1186050

Étant donné que l'objet Point de NetTopologiySuite ne contient pas de constructeur sans paramètre, vous ne pouvez pas facilement mapper le JSON pendant la déserailisation.

Mais, vous pouvez facilement créer votre propre objet Location, puis mapper les valeurs à l'objet Point de NetTopologySuite dans votre boucle.

Tout d'abord, définissez un nouvel objet Location ...

public class Location
{
    public double Longitude { get; set; }
    public double Latitude { get; set; }
    public int SRID { get; set; }
}

Ensuite, mettez à jour la ligne d'emplacement de votre JSON avec la ligne ci-dessous pour définir l'objet Location:

"Location": {"Longitude":-122.4194155, "Latitude":37.7749295, "SRID":4326},

JSON complet:

[{
        "Email": "[email protected]",
        "Username": "Lola",
        "Gender": "female",
        "DateOfBirth": "1994-02-21",
        "Password": "password",
        "Created": "2017-08-02",
        "LastActive": "2017-08-02",
        "Introduction": "blah blah blah",
        "LookingFor": "blah blah blah",
        "City": "San Francisco",
        "Country": "United States",
        "Longitude": -122.431297,
        "Latitude": 37.773972,
        "Location": {"Longitude":-122.4194155, "Latitude":37.7749295, "SRID":4326},
        "Photos": [{
            "url": "https://randomuser.me/api/portraits/women/3.jpg",
            "isMain": true,
            "description": "Non deserunt labore sunt ex laboris et adipisicing ullamco officia minim."
        }]
    }]

Ensuite, mettez à jour votre objet User pour utiliser votre nouvel objet Location et définissez l'attribut JsonIgnore sur l'objet Point de NetTopologySuite:

public class User : IdentityUser<int>
{
    // member data here

    public Location Location { get; set; }

    [JsonIgnore]
    public Point LocationPoint { get; set; } // has lat/lng data points
}

Enfin, mettez à jour votre boucle foreach pour mapper les données ...

foreach (var user in users)
{
    user.Photos.SingleOrDefault().IsApproved = true;
    user.LocationPoint = new Point(user.Location.Longitude, user.Location.Latitude) {SRID = user.Location.SRID};
    _userManager.CreateAsync(user, "password").Wait();
    _userManager.AddToRoleAsync(user, "Member").Wait();
}

Cela dit, vous voudrez peut-être reconsidérer l'utilisation de l'objet Point de NetTopologySuite directement dans votre objet User, et utiliser à la place votre propre objet Location. Ensuite, vous transposeriez l'objet Point de NetTopologySuite plus près du code qui utilise réellement le point. Cela dépend vraiment de votre application.

1
quaabaam

Un peu tard pour la fête, mais voici mon point de vue à ce sujet: vous pouvez facilement facilement rendre le Point compatible avec vos paramètres Json Serializer actuels.

[DataContract]
public class GeoLocation : NetTopologySuite.Geometries.Point
{
    const int GoogleMapSRID = 4326 ;

    public GeoLocation(double latitude, double longitude)
        : base(x: longitude, y: latitude) =>
          base.SRID = GoogleMapsSRID;

    [DataMember]
    public double Longitude => base.X;

    [DataMember]
    public double Latitude => base.Y;
}

Les DataContract et DataMember sont clés ici:

new GeoLocation(42.9074, -78.7911).ToJson() => {"longitude":42.9074,"latitude":-78.7911}
0
Ahmed Alejo