2016-05-09 4 views
1

Я написал простой API, который читает json-файл и предоставляет эти данные через GET. Моя модель для контроллера выглядит следующим образом:Malformed Json для GET

public static class ServerListHandler 
{ 
    private static readonly string _serverListPath; 
    private static FileSystemWatcher _serverListWatcher; 
    private static string _servers; 

    public static string Servers 
    { 
     get 
     { 
      if(_serverListWatcher == null && File.Exists(_serverListPath)) 
      { 
       InitializeFileWatcher(); 
       ReadData(); 
      } 

      return _servers; 
     } 

     private set 
     { 
      _servers = value; 
     } 
    } 

    static ServerListHandler() 
    { 
     _serverListPath = Properties.Settings.Default.ServerListPath; 

     if(!File.Exists(_serverListPath)) 
     { 
      Debug.WriteLine("Could not find config with path: " + _serverListPath); 
     } 
     else 
     { 
      ReadData(); 
      InitializeFileWatcher(); 
     } 
    } 

    private static void InitializeFileWatcher() 
    { 
     _serverListWatcher = new FileSystemWatcher(Path.GetDirectoryName(_serverListPath)); 
     _serverListWatcher.EnableRaisingEvents = true; 

     _serverListWatcher.Deleted += OnServerListChanged; 
     _serverListWatcher.Changed += OnServerListChanged; 
     _serverListWatcher.Created += OnServerListChanged; 
     _serverListWatcher.Renamed += OnServerListChanged; 
    } 

    private static void OnServerListChanged(object sender, FileSystemEventArgs e) 
    { 
     ReadData(); 
    } 

    private static void ReadData() 
    { 
     try 
     { 
      string content = File.ReadAllText(_serverListPath); 
      Servers = content; 
     } 
     catch(Exception ex) 
     { 
      Debug.WriteLine("Could not read server file: " + ex); 
     }    
    } 
} 

Я добавил эту строку в WebApiConfig.cs, чтобы получить выход JSon

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); 

Исходный файл JSON выглядит следующим образом:

[ 
    { 
    "Name": "testing", 
    "IP": "127.0.0.1" 
    } 
] 

И результат GET:

"[\r\n {\r\n \"Name\": \"testing\",\r\n \"IP\": \"127.0.0.1\"\r\n }\r\n]\r\n" 

Конечно, результат не поддается анализу для Json.NET. Теперь мой вопрос в том, должен ли я вручную разбирать строку json, которая подходит, или если я просто забыл включить/проверить что-то, чтобы включить правильный вывод json.

Редактировать

В соответствии с поручением это мой контроллер

public class ServersController : ApiController 
{ 
    public HttpResponseMessage GetAllServers() 
    { 
     if(ServerListHandler.Servers == null) 
      return Request.CreateResponse(HttpStatusCode.NoContent); 

     return Request.CreateResponse(HttpStatusCode.OK, ServerListHandler.Servers); 
    } 
} 
+0

Как вы просматриваете этот JSON? В отладчике вывести его в файл? – CathalMF

+0

А также покажите код, который фактически возвращает результат из вашего API. – CathalMF

+0

Вы имеете в виду результат или оригинал? Оригинал - это файл в моем каталоге веб-сервисов, и результат получается из моего веб-браузера (или может быть получен путем отладки веб-приложения, это тот же результат) – chris579

ответ

2

Проблема здесь состоит в том, что Web API по умолчанию предполагается, что он несет ответственность за сериализации что вы даете ему. Для большинства случаев использования это именно то, что вы хотели бы. Но если ваш контент уже JSON, веб-API не имеет возможности это знать; он будет счастливо повторно сериализовать строку, добавив дополнительные кавычки и обратную косую черту в этом процессе.

Чтобы вернуть строку JSON нетронутой, вам необходимо явно создать объект содержимого ответа (вместо того, чтобы позволить веб-API создавать его), убедившись, что этот тип носителя настроен так, чтобы последующие клиенты все еще интерпретировали его как JSON (скорее чем обычный текст). Вот пересмотренный метод контроллера:

public HttpResponseMessage GetAllServers() 
{ 
    if(ServerListHandler.Servers == null) 
     return Request.CreateResponse(HttpStatusCode.NoContent); 

    HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK); 
    response.Content = new StringContent(ServerListHandler.Servers, Encoding.UTF8, "application/json"); 
    return response; 
} 

Другое возможное (но менее эффективное) решение для десериализации вашего JSON в объект, а затем вернуть этот объект из метода контроллера, как это было предложено @CathalMF в комментариях. После этого Web API снова преобразует объект обратно в JSON, когда он создаст ответ.