0

I'm building an app for modifying existing json files. I have made all the classes that correspond to my json code. Most of the times I need to copy whole json collection and then just change a few things (like id, index, etc.).

I successfully copy and add whole collection and when I try to change that something in that collection it makes changes in the collection from which I did the copying. Could you please tell me what am I doing wrong?

private void addFlightButton_Click(object sender, RoutedEventArgs e) {
  var originDestinationGroup = jsonObject.search.originDestinationGroup;
  OriginDestinationGroup oDGitem = originDestinationGroup.Last();
  var departureDateGroup = oDGitem.departureDateGroup;
  DepartureDateGroup dDGitem = departureDateGroup.Last();
  var originDestinationOptionRef = dDGitem.originDestinationOptionRef;
  OriginDestinationOptionRef oDORitem = originDestinationOptionRef.Last();

  originDestinationOptionRef.Add(oDORitem);
  char uriNumber = oDORitem.uri[oDORitem.uri.Length - 1];
  string uriString = oDORitem.uri.TrimEnd(oDORitem.uri[oDORitem.uri.Length - 1]);
  int idNumber = Convert.ToInt32(oDORitem.id);
  int indexNumber = oDORitem.index;

  uriNumber++;
  idNumber++;
  indexNumber++;

  OriginDestinationOptionRef oDORitemModify = originDestinationOptionRef.Last();
  oDORitemModify.uri = uriString + uriNumber.ToString();
  oDORitemModify.id = idNumber.ToString();
  oDORitemModify.index = indexNumber;
}

json Response - Not modified:

"search": {
  "originDestinationGroup": [{
        "departureDateGroup": [{
              "originDestinationOptionRef": [{
                  "uri": "option/1",
                  "id": "1",
                  "index": 0
                },
                {
                  "uri": "option/2",
                  "id": "2",
                  "index": 1
                }
              ]

json Response - Modified by my code:

"search": {
  "originDestinationGroup": [{
        "departureDateGroup": [{
              "originDestinationOptionRef": [{
                  "uri": "option/1",
                  "id": "1",
                  "index": 0
                },
                {
                  "uri": "option/3",
                  "id": "3",
                  "index": 2
                },
                {
                  "uri": "option/3",
                  "id": "3",
                  "index": 2
                }
              ]

json Response - How it suppose to be modified:

"search": {
  "originDestinationGroup": [{
        "departureDateGroup": [{
              "originDestinationOptionRef": [{
                  "uri": "/option/1",
                  "id": "1",
                  "index": 0
                },
                {
                  "uri": "option/2",
                  "id": "2",
                  "index": 1
                },
                {
                  "uri": "option/3",
                  "id": "3",
                  "index": 2
                }
              ]

Classes:

public class Search {
  public List<OriginDestinationGroup> originDestinationGroup { get; set; }
}
public class OriginDestinationGroup {
  public List<DepartureDateGroup> departureDateGroup { get; set; }
}
public class DepartureDateGroup {
  public List<OriginDestinationOptionRef> originDestinationOptionRef { get; set; }
}

public class OriginDestinationOptionRef {
  public string uri { get; set; }
  public string id { get; set; }
  public int index { get; set; }
}

Thank you in advance.

Rickest Rick
  • 1,519
  • 1
  • 15
  • 28
Adicili
  • 67
  • 1
  • 9
  • Can you do some simplier JSON for what it has, what it's supposed to be, and what it actually does? With all the extra numbers/letters in there I can't easily tell what the differences are. – gilliduck Jan 02 '18 at 15:36
  • _"when I try to change that something in that collection it makes changes in the colection from which I did the copying"_ - could be because you're changing the actual reference within the collection. Make a copy of the original - which can be as easy as calling `ToList()` on the collection - and change the copy. – stuartd Jan 02 '18 at 15:39
  • @gilliduck I changed it. Is this better for you? – Adicili Jan 02 '18 at 15:44
  • @stuartd Could you please refer to the actual part of the code where I am changing actual reference within the collection. Thank you – Adicili Jan 02 '18 at 15:45
  • @Adicili now you've simplified the code it's apparent, as per the answers below! – stuartd Jan 02 '18 at 16:06

2 Answers2

2

So, you're taking the last item of the collection:

OriginDestinationOptionRef oDORitem = originDestinationOptionRef.Last();

And adding it to the same collection:

originDestinationOptionRef.Add(oDORitem);

So the collection now contains two pointers to the same object. Then you take the last object in the collection and modify it, but because you've duplicated the reference instead of creating a new object, both the new entry and the one you've copied will change. So you just need to create a new OriginDestinationOptionRef and add that to the collection, instead of copying an existing one.

John M
  • 2,510
  • 6
  • 23
  • 31
  • Thank you so much, this answer really helped me. Just one question. Since mine json is much more complicated than this one I put here I really need to copy everything from last item and than just make a few changes. and when I add newItem by your way, that new item is blank and I need to add each item sepparatelly. So how to copy and then modify? – Adicili Jan 02 '18 at 16:48
  • You can check out the docs for [Object.MemberwiseClone](https://msdn.microsoft.com/en-us/library/system.object.memberwiseclone(v=vs.110).aspx) but note that this is a "shallow copy" - so it's fine with properties that are simple types, but if you have properties that are references to _other_ objects you'll need to copy those manually - but there's an example in the docs. – John M Jan 02 '18 at 19:24
1

This is where you go wrong:

OriginDestinationOptionRef oDORitem = originDestinationOptionRef.Last();
originDestinationOptionRef.Add(oDORitem);

This code gets the last item from the list and then adds a new reference to that very same object to the very same list. So the list becomes longer by 1 entry, but the last two entries are now pointing to the same object in memory (the original object, which you then proceed to change).

To solve this, create a new OriginDestinationOptionRef object:

var newItem = new OriginDestinationOptionRef();
originDestinationOptionRef.Add(newItem);

Then use your existing logic to set the properties of newItem.

Peter B
  • 22,460
  • 5
  • 32
  • 69
  • Thank you so much, this answer really helped me. Just one question. Since mine json is much more complicated than this one I put here I really need to copy everything from last item and than just make a few changes. and when I add newItem by your way, that new item is blank and I need to add each item sepparatelly. So how to copy and then modify? – Adicili Jan 02 '18 at 16:46
  • There is no way around copying all properties from the source to the target, one way or another. See e.g. here: https://stackoverflow.com/q/930433/1220550 for guidance on some possible approaches that can be useful in more scenarios than just this one. – Peter B Jan 02 '18 at 18:29