How to replace multiple values in json file using c#? - c#

I need to replace the Filename and Location in json file with new value if the API number exists in json or else it should add new json array with API,File and location.I have written foreach loop to do it but each time the contents are added to list the if condition takes the new api added and compares to the list so it keeps adding the same api again and again to json file.Plz help me resolve this..
List<DPIndex> items = JsonConvert.DeserializeObject<List<DPIndex>>(json);
foreach (var item in items)
{
foreach (var list in dpIndexList)
{
if (item.API == list.API)
{
item.File = list.File;
item.Location = list.Location;
}
else
{
item.API = list.API;
item.File = list.File;
item.Location = list.Location;
}
}
dpNewIndexList.Add(item);
}
string dpIdxObj = JsonConvert.SerializeObject(dpNewIndexList, Formatting.Indented);
Json file is as below:
[
{
"API": "422833682700000000",
"File": "daf420.dat.07-31-2019",
"Location": 2922
},
{
"API": "422833682700000000",
"File": "daf420.dat.07-31-2019",
"Location": 2922
}
]

Here is a code which will add the item to dpIndexList if an item with such "API" doesn't exist there, or will update the item in that list, if an item with such "API" exists:
foreach (var item in items)
{
// Check if the item with such API already exists in dpIndexList
var foundItem = dpIndexList.FirstOrDefault(dpItem => dpItem.API == item.API);
if (foundItem != null)
{
// Exists. Update the item in dpIndexList
foundItem.File = item.File;
foundItem.Location = item.Location;
}
else
{
// Doesn't exist. Adding to dpIndexList
dpIndexList.Add(item);
}
}
For testing locally I used the following dummy lists, and it worked:
var dpIndexList = new List<DPIndex>()
{
new DPIndex
{
API = "1",
File = "File_1_ORIG",
Location = 1111
},
new DPIndex
{
API = "2",
File = "File_2_ORIG",
Location = 2222
},
};
var items = new List<DPIndex>()
{
// Item, which exists in dpIndexList (should update the original)
new DPIndex
{
API = "2",
File = "File_2_UPDATE",
Location = 3333
},
// New item, which doesn't exist in dpIndexList (should be added)
new DPIndex
{
API = "3",
File = "File_3_NEW",
Location = 3333,
},
// Item, which should UPDATE the one above (should update that one)
new DPIndex
{
API = "3",
File = "File_3_UPDATED",
Location = 3333
},
};
P.S. Don't forget to add using System.Linq; to the top of the file.

After going through your code. It looks like you are getting values form
same object and changing it over and over again
Look at the example below
List<DPIndex> dpIndexList = new List<DPIndex>();
DPIndex index = new DPIndex() {
API = "API.1",
File="API1",
Location="1"
};
dpIndexList.Add(index);
index.API = "API.2";
As you can see I have added the index object in List dpIndexList
but after adding it I changed the value of API in same index object which leads to changed value in dpIndex List also.
You are doing the same thing with item here you are changing its state in each iteration. So in the end all values will become what was the final iteration of the loop
I say you create a object in each iteration and add it to list
And for updation use lambda
foreach (var item in items)
{
foreach (var list in dpIndexList)
{
DPIndex it = new DPIndex();
if (item.API == list.API)
{
it.File = list.File;
it.Location = list.Location;
dpNewIndexList.RemoveAll(x=> x.API == list.API);
}
else
{
it.API = list.API;
it.File = list.File;
it.Location = list.Location;
}
dpNewIndexList.Add(it);
}
}
I beleive this would help you

Related

System.Text.Json modify data on the fly

I got a json as input. I don't know exact structure of that file. I need only add object to "KnownCollection" which may be in file or not. So if there is a collection add item into it, if there is not create a collection with an item. Question is how to do that with System.Text.Json, we used it and I don't want to add dependency on Newtonsoft
{
"UnknownProperty": 1,
"KnownCollection": [{
"ItemProperty1": "1",
"ItemProperty2": 2
}],
// More unknown properties
}
var item = new {ItemProperty1 = "2", ItemProperty2 = 2};
var fileContent = File.ReadAllBytes(filePath);
using var jsonDocument = JsonDocument.Parse(fileContent);
var knownCollection = jsonDocument.RootElement.GetProperty("KnownCollection");
//How to add item to knownCollection?
You could add the item to array like below:
[HttpGet]
public string Index()
{
var fileContent = System.IO.File.ReadAllBytes("filePath");
using (MemoryStream memoryStream1 = new MemoryStream())
{
using (Utf8JsonWriter utf8JsonWriter1 = new Utf8JsonWriter(memoryStream1))
{
using (JsonDocument jsonDocument = JsonDocument.Parse(fileContent))
{
utf8JsonWriter1.WriteStartObject();
foreach (var element in jsonDocument.RootElement.EnumerateObject())
{
if (element.Name == "KnownCollection")
{
utf8JsonWriter1.WritePropertyName(element.Name);
utf8JsonWriter1.WriteStartArray();
// Staring new object
utf8JsonWriter1.WriteStartObject();
utf8JsonWriter1.WriteString("ItemProperty1", "2");
utf8JsonWriter1.WriteNumber("ItemProperty2", 2);
utf8JsonWriter1.WriteEndObject();
// Copying existing values from "KnownCollection" array
foreach (var testDataElement in element.Value.EnumerateArray())
{
testDataElement.WriteTo(utf8JsonWriter1);
}
utf8JsonWriter1.WriteEndArray();
}
else
{
element.WriteTo(utf8JsonWriter1);
}
}
utf8JsonWriter1.WriteEndObject();
}
}
var resultJson = Encoding.UTF8.GetString(memoryStream1.ToArray());
return resultJson;
}
}
Result:

List not updating in .NET

I tried to update a list . I tried the code in debug mode , and the code was executed without any errors. But the value was not updated. Why would this be? I have shared the code below.
foreach (var r in respondents)
{
foreach(var v in completesMap.VendorView)
{
if(v.Value.Contains(r.Status))
{
r.Status=v.Key;
break;
}
}
}
completesMap.VendorView is a key-value pair which I hard-coded in appsettings.json file , respondents is a Dto
I have created an example using your code and it works.
You can see how it works at this link. You can also copy and paste that code to your IDE and debug it & see if it works at your machine also.
Working Code
List<Respondent> respondents = new List<Respondent>()
{
new Respondent { Status = "Active"},
new Respondent { Status = "Active"},
new Respondent { Status = "InActive"},
};
var completesMap = new Map
{
VendorView = new List<VendorView>()
{
new VendorView{ Value = "This is Active" , Key = "Key1" },
new VendorView{ Value = "this is not active", Key = "Key2" }
}
};
foreach (var r in respondents)
{
foreach (var v in completesMap.VendorView)
{
if (v.Value.Contains(r.Status))
{
r.Status = v.Key;
break;
}
}
}
var x = respondents[1].Status;
Debugger Output

Return the number of times a string occurs as a property in a list of custom objects

I'm trying to return a list with the number of times a property has a value set.
I'm trying to do this without having to hardcode the value to look for, so if something changes on the backend I won't have to add a new line of code.
Currently I have it working, but I have set the values manually.
listCounts.Add(testList.Count(item => item.title == "Blah"));
listCounts.Add(testList.Count(item => item.title == null));
listCounts.Add(testListt.Count(item => item.title == "test"));
listCounts.Add(testList.Count(item => item.title == "Blarg"));
This works currently but if anything chaanges, i'll have to go in and made changes to the code which is what I am trying to avoid
Depends on what you're trying to do really. It looks like you want the count of wach of those keys (the titles)?
One way would be to group by your title to give the counts, eg.
var listCounts = testList.GroupBy(item => item.title);
As an example of using this:
class Item
{
public string title;
}
static void Main(string[] args)
{
var testList = new List<Item>
{
new Item { title = "Blah" },
new Item { title = "Blah" },
new Item { title = "Blah" },
new Item { title = null },
new Item { title = null },
new Item { title = "test" },
new Item { title = "test" },
new Item { title = "test" },
new Item { title = "test" }
};
var listCounts = testList.GroupBy(item => item.title);
foreach (var count in listCounts)
{
Console.WriteLine("{0}: {1}", count.Key ?? string.Empty, count.Count());
}
Console.ReadKey();
}
The disadvantage is you're getting the count each time - like I said, it depends on what you're trying to achieve. A simple change would make this a dicationary (string, int), whereby each title would be a key, and the value would be the number of times the title appears.
EDIT
To use a dictionary, change the listCounts line to:
var listCounts = testList.GroupBy(t => t.title).ToDictionary(i => i.Key ?? string.Empty, i => i.Count());
(note that a key cannot be null, hence the i.Key ?? string.Empty workaround, should be fine for your purposes)
We don't know what your backend is, but it would seem you need to retrieve the values from it.
//string[] myStrings = new string[] { "Blah", null, "test", "Blarg" };
string[] myStrings = _backEnd.RetrieveValues();
listCounts.Add(testList.Count(item => myStrings.Contains(item)));

create NetSuite ItemFulfillment containg items with lot/serial info

I am using SuiteTalk web services (v. 2013_2) . I am trying to create an ItemFulfillment where the items in it were related to items that had a lot or serial number.
When I try to save this item fulfillment into NetSuite I get an error of :
Please commit inventorydetail on this line.
I was attempting to set the itemFulfillment.serialNumbers and itemFulfillment.binNumbers when I create the itemFulfillmentItem.
For example I set
nsIfItem.serialNumbers = "SNum(5)"
nsIfItem.binNumbers = "BNum(5)"
based on those properties being- A comma delimited list of serial or LOT numbers. If entering serial numbers there must be a number for each item.
Lot numbers must be entered in a format of LOT#(Quantity).
For example, to enter a quantity of 100 items as Lot number ABC1234, enter ABC1234(100).
Do I also need to set something else on the itemFulfillment or how do I get rid of that error.
I'm not sure if this question is still active, but I had the same issue and iI couldn't find much help on it. I solved this issue by creating the inventory assignment objects and adding to the transaction.
First, create the initialize ref for Item Fulfillment and assign the returned record to a variable:
InitializeRecord ir = new InitializeRecord();
ir.type = InitializeType.itemFulfillment;
InitializeRef iref = new InitializeRef();
iref.typeSpecified = true;
iref.type = InitializeRefType.salesOrder;
iref.internalId = 'Sales Order internalID';
ir.reference = iref;
ReadResponse getInitResp = _service.initialize(ir);
ItemFulfillment ifrec = (ItemFulfillment)getInitResp.record;
Get the list of items on the initialized transaction:
ItemFulfillmentItemList ifitemlist = ifrec.itemList;
Create a list to which to add each unique item being fulfilled:
List<ItemFulfillmentItem> ifitems = new List<ItemFulfillmentItem>();
Run the following code for each item in initialized transaction's item list:
If the current line item has already been added to the ifitems list, add the current Fulfillment line as an assignment to that item:
InventoryAssignment assignment = new InventoryAssignment
{
issueInventoryNumber = new RecordRef { internalId = 'internalID',
type = 'RecordType',
typeSpecified = true
}
};
List<InventoryAssignment> list = new List<InventoryAssignment>();
list.Add(assignment);
ifitemlist.item[b].inventoryDetail = new InventoryDetail
{
inventoryAssignmentList = new InventoryAssignmentList
{
inventoryAssignment = list.ToArray()
}
};
ifitemlist.item[b].quantity += 'quantity shipped';
If the line item has not yet been added, create new line item:
ItemFulfillmentItem ffItem = new ItemFulfillmentItem();
ffItem.item = ifitemlist.item[b].item;
ffItem.itemReceive = true;
ffItem.itemReceiveSpecified = true;
ffItem.itemIsFulfilled = true;
itemIsFulfilled = true;
ffItem.itemIsFulfilledSpecified = true;
ffItem.orderLineSpecified = true;
ffItem.orderLine = ifitemlist.item[b].orderLine;
//Check if serialized
if (Your fulfillment item contains serialized data)
{
ffItem.serialNumbers = 'Serial numbers';
InventoryAssignment assignment = new InventoryAssignment
{
issueInventoryNumber = new RecordRef {
internalId = 'Inventory internal ID',
type = RecordType,
typeSpecified = true
}
};
ffItem.inventoryDetail = new InventoryDetail
{
inventoryAssignmentList = new InventoryAssignmentList
{
inventoryAssignment = new InventoryAssignment[]
{
assignment
},
replaceAll = false
},
nullFieldList = new string[] { },
customForm = new RecordRef { }
};
}
ffItem.quantity = 'QUANTITY SHIPPED';
ffItem.quantitySpecified = true;
ifitems.Add(ffItem);
Finally, add your "ifitems" list to your Item Fulfillment and add this to NetSuite:
ItemFulfillmentItemList ifitemlistToFulfill = new ItemFulfillmentItemList();
ifitemlistToFulfill.replaceAll = false;
ifitemlistToFulfill.item = ifitems.ToArray();
ItemFulfillment newItemFulfill = new ItemFulfillment();
newItemFulfill.itemList = ifitemlistToFulfill;
_service.add(newItemFulfill);

Linq query for searching an object inside a dictionary having list of lists as values

I'm searching a sorted dictionary with a key of type datetime and values as list of objects. What I need to find is the latest value(based on a property on the object) for each object in the dictionary. My object has 3 properties : a name, a value and a date when it was created. My dictionary is sorted by latest date in descending order.
I have got this working somehow, but I'm sure there is a shortcut for this using LINQ. Please note that I'm using .NET 3.5. Could you please help? Please dont get put off by the huge amount code below as I have added it for clarity and i'm only looking for a linq query to query inside a list of list objects.
Code below:
public void Should_link_recent_data_together()
{
var data = TimeSeriesDataFactoryEx.GetData();
var allAttributes = new List<string>()
{
TimeSeriesConstants.TOTAL_COST_CODE,
TimeSeriesConstants.TOTAL_VALUE_CODE,
TimeSeriesConstants.SOURCE_CODE
};
var latestList = new List<TimeSeries>();
var allValues = data.Values.ToList();
#region HOW DO I DO THIS USING LINQ?
bool found = false;
foreach (var attribute in allAttributes)
{
found = false;
foreach (var tsData in allValues)
{
foreach (var ts in tsData)
{
if (ts.MetricName == attribute && !string.IsNullOrEmpty(ts.MetricValue))
{
latestList.Add(ts);
found = true;
break;
}
}
if (found)
break;
}
}
#endregion
Assert.IsTrue(latestList.Count == 3);
Assert.IsTrue(latestList.Where(x => x.MetricName == TimeSeriesConstants.TOTAL_COST_CODE).First().MetricValue == "1");
Assert.IsTrue(latestList.Where(x => x.MetricName == TimeSeriesConstants.TOTAL_VALUE_CODE).First().MetricValue == "2");
Assert.IsTrue(latestList.Where(x => x.MetricName == TimeSeriesConstants.SOURCE_CODE).First().MetricValue == "gp");
Assert.IsTrue(latestList.Where(x => x.MetricName == TimeSeriesConstants.SOURCE_CODE).First().Quarter == DateTime.Today.AddMonths(-3));
}
internal class TimeSeriesDataFactoryEx
{
public static SortedDictionary<DateTime?,List<TimeSeries>> GetData()
{
return new SortedDictionary<DateTime?, List<TimeSeries>>(new DateComparer())
{
{
DateTime.Today, new List<TimeSeries>()
{
new TimeSeries()
{
Quarter = DateTime.Today,
MetricValue = "1",
MetricName = TimeSeriesConstants.TOTAL_COST_CODE
},
new TimeSeries()
{
Quarter = DateTime.Today,
MetricValue = "2",
MetricName = TimeSeriesConstants.TOTAL_VALUE_CODE
},
new TimeSeries()
{
Quarter = DateTime.Today,
MetricValue = "",
MetricName = TimeSeriesConstants.SOURCE_CODE
}
}
},
{
DateTime.Today.AddMonths(-3), new List<TimeSeries>()
{
new TimeSeries()
{
Quarter = DateTime.Today.AddMonths(-3),
MetricValue = "3",
MetricName = TimeSeriesConstants.TOTAL_COST_CODE
},
new TimeSeries()
{
Quarter = DateTime.Today.AddMonths(-3),
MetricValue = "4",
MetricName = TimeSeriesConstants.TOTAL_VALUE_CODE
},
new TimeSeries()
{
Quarter = DateTime.Today.AddMonths(-3),
MetricValue = "gp",
MetricName =TimeSeriesConstants.SOURCE_CODE
}
}
}
};
}
}
So, assuming I understand your question right, say you have a dictionary like so:
{ Key = "1/1/1900", Value = List Of Objects, of which each has a DateTimeProperty }
...
{ Key = "1/4/1900", Value = List Of Objects, of which each has a DateTimeProperty }
And you are looking to find a set of objects from your dictionary, where it's the latest by time of each key, then you can do this pretty simply with linq:
var latestItems = data.SelectMany(kvp =>
kvp.Value.OrderByDescending(value => value.Quarter).Take(1)
);
This query finds the most recent object in each bucket and then returns that as a single set (not an enumerable of enumerables). You can change the selector inside the SelectMany to find elements in each set as much as you want, as long as you return an IEnumerable from that callback.

Categories

Resources