2015-09-16 2 views
1

Я пытаюсь Получать JSON, используя следующий классNpgsqlTypes.NpgsqlPolygon отправка JSON

public class LayerData : DataObject 
    { 
     [PrimaryKeyField("id")] 
     public long Id { get; set; } 

     [PrimaryKeyField("identifier")] 
     public Guid Identifier { get; set; } 

     [DataField("name")] 
     public string Name { get; set; } 

     [DataField("value")] 
     public string Value { get; set; } 

     [DataField("coordinates")] 
     public NpgsqlTypes.NpgsqlPolygon Coordinates { get; set; } 

     [DataField("type")] 
     public long Type { get; set; } 

     [DataField("layer_id")] 
     public long LayerId { get; set; } 

    } 

я получаю проблемы при отправке NpgsqlTypes.NpgsqlPolygon с

"Message": "An error has occurred.", 
"ExceptionMessage": "Object reference not set to an instance of an object.", 
"ExceptionType": "System.NullReferenceException", 
"StackTrace": " at NpgsqlTypes.NpgsqlPolygon.System.Collections.IEnumerable.GetEnumerator()\r\n 

Когда я называю прибудете я Получать этот JSON

{ 
    "Id": 739, 
    "Identifier": "570a2848-88b0-467f-b4aa-da693f6b12b2", 
    "Name": "test", 
    "Value": "gsdfsdf", 
    "Coordinates": [{ 
     "X": 2.0, 
     "Y": 3.0 
    }, 
    { 
     "X": 4.0, 
     "Y": 5.0 
    }], 
    "Type": 1, 
    "LayerId": 4 
} 

, но когда я пытаюсь опубликовать я получаю эти ошибки

{ 
    "Identifier":"571a2848-88b0-467f-b4aa-da693f6b12b2", 
    "Name": "test", 
    "Value": "gsdfsdf", 
    "Coordinates": [{ 
     "X": 2.0, 
     "Y": 3.0 
    }, 
    { 
     "X": 4.0, 
     "Y": 5.0 
    }], 
    "Type": 1, 
    "LayerId": 4 
} 

Любые идеи, почему это не нужно? В теории, если я получаю тип Json, я могу отправить его с использованием той же структуры.

+0

возможности сериализации JSON вы получите в этот класс вы? Также вы уверены, что тот же самый класс используется на стороне сервера для десериализации? –

+0

есть пример выше того, что json я получаю и что json я посылаю, идея json, которую я посылаю, не работает – moodle

+0

ОК, у меня есть идея, просто хотела получить подтверждение. В любом случае, мой ответ был основан на предположении. Надеюсь, поможет. –

ответ

1

Вы не указали, какой JSON-десериализатор вы используете, но я думаю, что ваша проблема в том, что ничто не создает экземпляр для свойства Coordinates в вашем целевом LayerData экземпляре.

Я либо добавить конструктор LayerData который инициализирует Coordinates так:

public LayerData() 
{ 
    Coordinates = new NpgsqlTypes.NpgsqlPolygon(); 
} 

или инициализировать свойство экземпляра перед передачей его в десериализации, как это:

layerData.Coordinates = new NpgsqlTypes.NpgsqlPolygon(); 

EDIT 1

У меня было пару минут, поэтому я создал простую e test:

using System; 
using NpgsqlTypes; 
using Newtonsoft.Json; 

namespace NpgsqlTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var source = new TestDto 
      { 
       Coord = new NpgsqlPolygon(
        new NpgsqlPoint(2.0, 3.0), 
        new NpgsqlPoint(4.0, 5.0) 
       ) 
      }; 
      string json = JsonConvert.SerializeObject(source); 

      var result = JsonConvert.DeserializeObject<TestDto>(json); 
      double x = result.Coord[0].X; 
     } 
    } 

    public class TestDto 
    { 
     public NpgsqlPolygon Coord { get; set; } 
    } 
} 

Выполнение этого действия, я получил ту же исключение с использованием NULL-ссылки. В частности, исключение составляет Add метод NpgsqlPolygon. А?

Итак, я отправился в github and looked at the Npgsql source. Реализация NpgsqlPolygon использует приватное поле под названием _points для хранения списка координат. Проблема в том, что это struct и не имеет конструктора по умолчанию, но поле _points инициализируется только в конструкторах. Если вы используете конструкцию по умолчанию (что будет делать десериализатор Newtonsoft), то поле _points никогда не будет инициализировано.

вручную, создавая экземпляр и добавив значение для него имеет ту же проблему:

var coord = new NpgsqlPolygon(); 
coord.Add(new NpgsqlPoint(1.0, 2.0)); // throws exception 

Однако, вы можете использовать один из конструкторов не по умолчанию, и он будет работать:

var coord = new NpgsqlPolygon(1); 
coord.Add(new NpgsqlPoint(1.0, 2.0)); // no exception this time 

Это, кажется, ошибка в текущей версии Npgsql (3.0.2 - это то, что я получил от NuGet).

Я попробовал пару вещей, чтобы получить десериализацию для работы, например, добавить конструктор в класс TestDto или использовать JsonConvert.PopulateObject на экземпляре, который я правильно построил, но не работал.

На данный момент, мои предложения будут:

  • Пробуйте сериалайзер (вам нужно добавить конструктор правильно инициализировать свойство).
  • Потяните источник Npgsql из github и создайте собственную версию с необходимым исправлением.

EDIT 2

Другое дело, иметь в виду, что NpgsqlTypes определяются провайдером ADO.NET. Таким образом, спорная практика заключается в том, чтобы использовать их вне чего-то вроде слоя данных. Представляется, что они также считаются неизменными (хотя структура NpgsqlPolygon реализует IList<>, что подразумевает изменчивость).

Вы не указали ни одного контекста, в котором используется JSON, который используется для заполнения вашего класса LayerData, но для меня сериализация подразумевает, что он используется для распространения данных по уровням.

Таким образом, лучшим решением может быть создание набора пользовательских классов для представления данных многоугольника в вашем классе контрактов данных, а затем реализация некоторого типа данных в вашем слое данных для записи его в правильно построенные экземпляры NpgsqlPolygon.

+0

Я использую newtonsoft.Json, если я использую любой другой объект, я его создаю, он отлично работает, но когда я использую эту головную боль, я не могу передать эти координаты – moodle

0

В JSON «координаты» - это массив, но в классе это один класс. Это также объясняет, почему он терпит неудачу в IEnumerable.GetEnumerator(), потому что он рассматривает его как список.

Чтобы дать понять, как исправить это, вы можете попробовать использовать json2chsarp.com для генерации классов, которые вы можете использовать для десериализации этого JSON. Из образца он генерировал следующее:

public class Coordinate 
{ 
    public double X { get; set; } 
    public double Y { get; set; } 
} 

public class RootObject 
{ 
    public int Id { get; set; } 
    public string Identifier { get; set; } 
    public string Name { get; set; } 
    public string Value { get; set; } 
    public List<Coordinate> Coordinates { get; set; } 
    public int Type { get; set; } 
    public int LayerId { get; set; } 
} 

Как вы можете видеть координаты генерируются как список