lunes, 28 de octubre de 2019

Newtonsoft Json.NET + JsonApiSerializer: Path 'data'...type requires a JSON array

Sample code

    class Program
    {
        private static readonly HttpClient client = new HttpClient();

        static void Main(string[] args)
        {
            var cats = ProcessCats().Result;

            foreach (var cat in cats)
            {
                Console.WriteLine(cat);
                Console.WriteLine();
            }
        }

        private static async Task<Cat[]> ProcessCats()
        {
            client.DefaultRequestHeaders.Accept.Clear();
//...

            var stream = await client.GetStreamAsync("https://myapi/cats");

            var serializerSettings = new JsonApiSerializerSettings();
            var serializer = JsonSerializer.CreateDefault(serializerSettings);

            using (var textReader = new StreamReader(stream))
            using (var jsonReader = new JsonTextReader(textReader))
                return serializer.Deserialize<Cat[]>(jsonReader);

        }
    }

   public class Cat
    {
        public string Name { get; set; }

        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.Append("class Cat {\n");
            sb.Append("  Name: ").Append(Name).Append("\n");
            sb.Append("}\n");
            return sb.ToString();
        }
    }


Error

Unhandled Exception: System.AggregateException: One or more errors occurred. (Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'Cat[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'data', line 1, position 8.) ---> Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'Cat[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'data', line 1, position 8.
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)
   at WebAPIClient.Program.ProcessCats() in /Users/esteban-work/tmp/delete/samples/csharp/getting-started/console-webapiclient/Program.cs:line 42
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at WebAPIClient.Program.Main(String[] args) in /Users/esteban-work/tmp/delete/samples/csharp/getting-started/console-webapiclient/Program.cs:line 17

Fix

Remember to check if the root element has an Id property.

   public class Cat
    {
        public string Id { get; set; }
        public string Name { get; set; }

        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.Append("class ContactForClient {\n");
            sb.Append("  Id: ").Append(Id).Append("\n");
            sb.Append("  Name: ").Append(Name).Append("\n");
            sb.Append("}\n");
            return sb.ToString();
        }
    }


References




miércoles, 23 de enero de 2019

nginx: [emerg] host not found in upstream "nodejs" enabling TLS in AWS EB

Error:

2019-01-23 22:44:55    ERROR   [Instance: i-xx] Command failed on instance. Return code: 1 Output: (TRUNCATED)... /etc/nginx/sites-enabled/elasticbeanstalk-nginx-docker-proxy.conf:11
nginx: [emerg] host not found in upstream "nodejs" in /etc/nginx/conf.d/https.conf:19
nginx: configuration file /etc/nginx/nginx.conf test failed
Failed to start nginx, abort deployment.
Hook /opt/elasticbeanstalk/hooks/appdeploy/enact/01flip.sh failed. For more detail, check /var/log/eb-activity.log using console or EB CLI.

I was using a .ebextensions/singlehttps.config sample file from a Node Web Server Elastic Beanstalk app, with something like this,

location / {
proxy_pass http://nodejs;
proxy_set_header Connection "";
proxy_http_version 1.1;

but no upstream declaration because according AWS doc, "the default nginx configuration forwards traffic to an upstream server named nodejs at 127.0.0.1:8081".

But this App is a docker one (which has a Node app running on port 3500), not a nodejs one.

Looking at the EB instance's /etc/nginx/conf.d dir, this file declares a default upstream for docker:

elasticbeanstalk-nginx-docker-upstream.conf:

upstream docker {
    server xx.xx.x.x:yyy;
    keepalive 256;
}

Then,


location / {
proxy_pass http://docker;
proxy_set_header Connection "";
proxy_http_version 1.1;


domingo, 13 de enero de 2019

rb-inotify requires Ruby version >= 2.2 (installing compass)

compass 1.0.3 depends on rb-inotify >= 0.9 and rb-inotify launched a new version on December 15, 2018 which depends on Ruby >= 2.2 (the Ruby version installed through 'apt-get install -y ruby-full' on node:6.10 is 'ruby 2.1.5p273')

# lock rb-inotify version because the next one (0.10.0) depends on ruby >= 2.2
RUN gem install --no-rdoc --no-ri rb-inotify -v 0.9.10
# -​-conservative to instruct it to use the existing rb-inotify (0.9.10) instead of resolving rb-inotify >= 0.9
RUN gem install --no-rdoc --no-ri compass -v 1.0.3 -- -​-conservative