Y.op
Y.op

Reputation: 79

JSON file Array interpreted as a string

I'm recovering Ajax data in C#, so I was creating a JSON file that has this format:

{
      "type": 2,
      "body": "Hello",
      "time": 120000,
      "ip": [
        "[\"192.168.10.1-192.168.10.254\",\"192.168.11.1-192.168.11.254\",\"192.168.12.1-192.168.11.20\",\"192.168.1.5-192.168.1.50\"]"
      ],
      "hash": "6e42b725e351576d123ba7d4fc1b48863e4485821e0edb73abb8801a09a99bc7",
      "exclue": "127.0.0.1 "
}

with that :

public void exportConf(int type, string body, int time, string[] SendIp, string lstIp)
{
    StringBuilder Sb = new StringBuilder();
    byte[] bytes = Encoding.UTF8.GetBytes("test");
    SHA256 crypt =  SHA256.Create();
    byte[] hashBytes = crypt.ComputeHash(bytes);
    foreach (byte a in hashBytes)
    {
        Sb.Append(a.ToString("x2"));
    }
    JObject data = new JObject(
        new JProperty("type", type),
        new JProperty("body", body),
        new JProperty("time", (time*60*1000)),
        new JProperty("ip", JArray.FromObject(SendIp)),
        new JProperty("hash", Sb.ToString()),
        new JProperty("exclue", lstIp)
        );

    System.IO.File.WriteAllText(System.IO.Path.GetTempPath()+"xyz.json", data.ToString());
}

I call this function from my JS :

$('.send').click(function () {
var subnet = [];
$('table tbody tr td input[type=checkbox]').each(function () {
    if ($(this).is(':checked')) {
        subnet.push($(this).val());
    }
});
idType = $(".slct-type select :selected").val();
body = $('.zoneEdit textarea').val();
time = $('input[name=timeout]').val();
lstIp = $('.zoneIp textarea').val();
if (subnet.length > 0) {
    $.ajax({
        url: '/Scripts/exportConf',
        type: "POST",
        data: { type: idType, body: body, time: time, Sendip: JSON.stringify(subnet), lstIp: lstIp },
        dataType: "json",
        success: function (data) {
            for (i = 0; i < data.length; i++) {
                if (data[i].id == idType) {
                } else {

                }
            }

        }
    });
} else {
    alertbox('danger', 'Error', 2000);
}

});

When I parse my JSON file like this :

        if (File.Exists(Path.GetTempPath() + "xyz.json"))
        {
            JObject data = JObject.Parse(File.ReadAllText(System.IO.Path.GetTempPath() + "xyz.json"));
            Console.Write(data["ip"]);

        }

data[' IP'] should normally be an array, but when I do data[' IP'][0], I get this :

["192.168.10.1-192.168.10.254","192.168.11.1-192.168.11.254","192.168.12.1-192.168.11.20","192.168.1.5-192.168.1.50"]

IP is not treated as an array, but as a single string, I don't know why. Do you have a solution?

EDIT : I've found the solution, you have to go "traditional" to the truth.

http://api.jquery.com/jQuery.param/

Thx !

    $('.send').click(function () {
    var subnet = [];
    $('table tbody tr td input[type=checkbox]').each(function () {
        if ($(this).is(':checked')) {
            subnet.push($(this).val());
        }
    });
    idType = $(".slct-type select :selected").val();
    body = $('.zoneEdit textarea').val();
    time = $('input[name=timeout]').val();
    lstIp = $('.zoneIp textarea').val();
    if (subnet.length > 0) {
        $.ajax({
            url: '/Scripts/exportConf',
            type: "POST",
            data: { type: idType, body: body, time: time, Sendip: subnet, lstIp: lstIp },
            traditional : true,
            dataType: "json",
            success: function (data) {
                for (i = 0; i < data.length; i++) {
                    if (data[i].id == idType) {
                    } else {

                    }
                }

            }
        });
    } else {
        alertbox('danger', 'Merci de selectionner un réseau', 2000);
    }
});

Upvotes: 0

Views: 77

Answers (2)

Emre Kabaoglu
Emre Kabaoglu

Reputation: 13146

Maybe perhaps it should be;

new JProperty("ip", JArray.FromObject(SendIp[0]))

Upvotes: 0

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131237

Your code doesn't generate a nested array, it generates an array that contains a single string value.

It would be a lot easier to generate the JSON string if you created a DTO and serialized it directly. It would also avoid generating so many temporary objects :

class MyDTO
{
    public int type{get;set;}
    public string body {get;set;}
    public int time {get;set;}
    public string[][] ip{get;set;}
    public string hash {get;set;}
    public string exclude {get;set;}
}

void Main()
{
    var myDto=new MyDTO{
        type=2,
        body="Hello",
        time=120000,
        ip=new []{
            new []{
                "192.168.10.1-192.168.10.254",
                "192.168.11.1-192.168.11.254",
                "192.168.12.1-192.168.11.20",
                "192.168.1.5-192.168.1.50"
            }
        },
        hash="6e42b725e351576d123ba7d4fc1b48863e4485821e0edb73abb8801a09a99bc7",
        exclude = "127.0.0.1"
    };

    var json=JsonConvert.SerializeObject(myDto,Newtonsoft.Json.Formatting.Indented);
    Console.WriteLine(json);
}

The result is :

{
  "type": 2,
  "body": "Hello",
  "time": 120000,
  "ip": [
    [
      "192.168.10.1-192.168.10.254",
      "192.168.11.1-192.168.11.254",
      "192.168.12.1-192.168.11.20",
      "192.168.1.5-192.168.1.50"
    ]
  ],
  "hash": "6e42b725e351576d123ba7d4fc1b48863e4485821e0edb73abb8801a09a99bc7",
  "exclude": "127.0.0.1"
}

UPDATE 1

If you don't want to use a DTO, you can use an anonymous type. The result will be the same:

    var myDto=new {
        type=2,
        body="Hello",
        time=120000,
        ip=new []{
            new []{
                "192.168.10.1-192.168.10.254",
                "192.168.11.1-192.168.11.254",
                "192.168.12.1-192.168.11.20",
                "192.168.1.5-192.168.1.50"
            }
        },
        hash="6e42b725e351576d123ba7d4fc1b48863e4485821e0edb73abb8801a09a99bc7",
        exclude = "127.0.0.1"
    };

You can deserialize the string to the DTO with JsonConvert.DeserializeObject :

var dto=JsonConvert.DeserializeObject<MyDTO>(json);
var fistRange=dto.ip[0][0];

Or you can deserialize to a dynamic object :

    dynamic result=JsonConvert.DeserializeObject<dynamic>(json);
    Console.WriteLine(result.ip[0][0]);

In both cases, the result will be :

192.168.10.1-192.168.10.254

UPDATE 2

The original code does not produce the result shown in the question. It generates a string array property that contains the IP ranges. This code :

    var sendIPs =new []{
                "192.168.10.1-192.168.10.254",
                "192.168.11.1-192.168.11.254",
                "192.168.12.1-192.168.11.20",
                "192.168.1.5-192.168.1.50"
            };
    var hashString = "6e42b725e351576d123ba7d4fc1b48863e4485821e0edb73abb8801a09a99bc7";                
    JObject data = new JObject(
        new JProperty("type", 2),
        new JProperty("body", "Hello"),
        new JProperty("time", 12000),
        new JProperty("ip", JArray.FromObject(sendIPs)),
        new JProperty("hash", hashString),
        new JProperty("exclue", "127.0.0.1")
    );
    var json = data.ToString();

Returns

{
  "type": 2,
  "body": "Hello",
  "time": 12000,
  "ip": [
    "192.168.10.1-192.168.10.254",
    "192.168.11.1-192.168.11.254",
    "192.168.12.1-192.168.11.20",
    "192.168.1.5-192.168.1.50"
  ],
  "hash": "6e42b725e351576d123ba7d4fc1b48863e4485821e0edb73abb8801a09a99bc7",
  "exclue": "127.0.0.1"
}

Perhaps SendIP contains an already serialized array string?

Upvotes: 1

Related Questions