You are really working uphill by doing this all untyped, but you can get the value you want this way:
list<Object> l = (list<Object>) meta.get('addressDetails');
map<String,Object> m = (map<String,Object>) l[0];
Integer i = (Integer) m.get('addressId');
Honestly, if you make use of the Apex type system, you will have an easier time working with the data. If you create a class for the incoming data structure, abbreviated as:
public class Meta{
public list<addressDetail> addressDetails {get; set;}
public class addressDetail{
public Integer addressId {get; set;}
}
}
you will be able to access the data from your JSON strings as so:
Meta MyMeta = (Meta) JSON.deserialize(viewPersonValue,Meta.class);
system.debug(MyMeta.addressDetails[0].addressId);
Answer from martin on Stack ExchangeYou are really working uphill by doing this all untyped, but you can get the value you want this way:
list<Object> l = (list<Object>) meta.get('addressDetails');
map<String,Object> m = (map<String,Object>) l[0];
Integer i = (Integer) m.get('addressId');
Honestly, if you make use of the Apex type system, you will have an easier time working with the data. If you create a class for the incoming data structure, abbreviated as:
public class Meta{
public list<addressDetail> addressDetails {get; set;}
public class addressDetail{
public Integer addressId {get; set;}
}
}
you will be able to access the data from your JSON strings as so:
Meta MyMeta = (Meta) JSON.deserialize(viewPersonValue,Meta.class);
system.debug(MyMeta.addressDetails[0].addressId);
May be this simple example can help
string viewPersonValue = '{"name":"John",
"age":30,
"cars":
{"car1":"Ford",
"car2":"BMW",
"car3":"Fiat"}
}';
Map<String, Object> meta = (Map<String, Object> JSON.deserializeUntyped(viewPersonValue);
Map<String, Object> carMap = (Map<String, Object>) meta.get('cars');
system.debug(carMap.get('car1'));
apex - Creating a Map with String, Object combination - Salesforce Stack Exchange
Using Maps in Apex (beginner)
dictionary - APEX: Assigning a Map without a Key to a List - Stack Overflow
Can't return Salesforce MAP<String, Object> using get - Stack Overflow
You cant convert the map to a list without an id. Alternatively why to convert it to List. Use the map itself. Below is a code example of how you can use it using your JSON response. For example, I want to insert this JSON response into the contact record, so I can map it using the MAP itself.:
@RestResource(urlMapping='/URIId/*') global class OwneriCRM {
@HttpPut
global static String UpdateOwnerinfo(){
RestRequest req= RestContext.request;
RestResponse res= RestContext.response;
res.addHeader('Content-type','application/JSON');
Map<String,Object> responseresult=new Map<String,Object>();
Map<String,Object> results= (Map<String,Object>)JSON.deserializeUntyped(req.requestBody.toString());
List<contact> insertList = new List<contact>();
for (String key : results.keySet()){
System.debug(results.get(key));
contact c= new contact();
c.ContactField__C = results.get(id);
c.ContactField1__C = results.get(city);
c.ContactField2__C = results.get(conference);
c.ContactField3__C = results.get(division);
c.ContactField3__C = results.get(full_name);
c.ContactField3__C = results.get(name);
insertList.add(c);
}
if(!insertList.Isempty()){
update insertList;
}
Question can be disregarded. Not sure if there is a way to withdraw the question.
Question was based on the fact that previous APIs had been sent in the following format:
{"data": {"more stuff": "stuff"} }
And the map key was 'data' with a list. In this scenario, the whole API was a list and the keys to the map were set in place with the actual values instead.
The problem is that key of your map is Id, is not String, you can see it from first debug message.
Unfortunately for your use case what Pavel described is totally true http://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_collections_maps_from_SObjects.htm
for your code to work the way you wanted to it has to be rewritten
Map<String, Account> Map_Task_Frequency = new Map<String,Account>();
for(Account a: [SELECT Name,Id
FROM Account
WHERE name = 'Any Company Name'] ){
Map_Task_Frequency.put(a.Name, a);
}
System.debug('------Task Map List------' + Map_Task_Frequency);
System.debug('*****Task Map*****' + Map_Task_Frequency.get('Any Company Name'));
which won't make much sense as you'll be referencing your account record by name and that is on your WHERE condition so you'll end up with only one value on your map containing the last account loaded.
Looking in to this question, I realized that the type system is inherently broken. They have "fixed" Maps, it seems, but in a way that no longer lets you mix and match some types, especially Object.
The list class is still broken, however:
class c1 {
}
class c2 extends c1 {
}
c1[] s = new c2[0];
Generally speaking, unless/until they fix the problem, you won't be able to be polymorphic this way; your classes that intend to call this class would also need to use Map<Object, Object>, which will involve some casting.
One thought I had would be to create an interface like this:
public interface keyValueMap {
Set<Object> getKeys();
Object[] getValues();
Object getKey(Object value);
Object setKey(Object key, Object value);
}
And then create specific wrappers:
public class StringSObjectMap implements KeyValueMap {
Map<String, SObject> values;
public StringSObjectMap(Map<String, SObject> values) {
this.values = values;
}
public StringSObjectMap() {
values = new Map<String, SObject>();
}
public Set<Object> getKeys() {
Set<Object> results = new Set<Object>();
for(String value: values.keySet()) {
results.add(value);
}
return results;
}
public Object[] getValues() {
return (Object[])values.values();
}
public Object getKey(Object value) {
return (Object)values.get((String)value);
}
public Object setKey(Object key, Object value) {
return values.put((String)key, (SObject)value);
}
}
Note that since we can't cast Set<SObject> to Set<Object>, we have to build a duplicate key set. Make sure you cache the results for performance reasons.
Finally, you can write your method to use the new interface:
public keyValueMap doSomething(keyValueMap inputMap) {
And to call it, you'd pass in the appropriate sub-wrapper:
keyValueMap results = doSomething(new StringSObjectMap(recordMap));
Depending on what you're doing, this may require additional post-processing to get the values back out.
You might also just leave the return type as Map<Object, Object> but you'll end up having to process the keys again, as demonstrated in the wrapper above. One additional step might help you here; you can pass in the type of return value you want:
public keyValueMap doSomething(keyValueMap inputMap, Type mapType) {
keyValueMap results = (keyValueMap)mapType.newInstance();
Called as:
keyValueMap results = doSomething(new StringSObjectMap(recordMap), StringSObjectMap.class);
You could also create a custom Iterator, but this doesn't work in for-each loops (but you can use iter.next/iter.hasnext):
public class KeyValue {
public Object key;
public Object value;
public KeyValue(Object k, Object v) {
key = k;
value = v;
}
}
public class StringSObjectIter implements Iterable<KeyValue>, Iterator<KeyValue> {
Map<String, SObject> values;
String[] keys;
public StringSObjectIter(Map<String, SObject> values) {
this.values = values;
}
StringSObjectIter(StringSObjectIter copy) {
values = copy.values;
keys = new List<String>(values.keySet());
}
public Boolean hasNext() {
return !keys.isEmpty();
}
public KeyValue next() {
String k = keys.remove(0);
return new KeyValue(k, values.get(k));
}
public Iterator<KeyValue> iterator() {
return new StringSObjectIter(this);
}
}
Which you can use in your method as:
public keyValueMap doSomething(Iterable<KeyValue> inputs) {
Iterator<KeyValue> iter = inputs.iterator();
while(iter.hasNext()) {
KeyValue value = iter.next();
...
Calling method for this:
keyValueMap results = doSomething(new StringSObjectIter(recordMap));
No, there isn't a better way. With Set, you can hack around it to some extent. But with a Map, you care about the values, not just the keys, so you can't do it without looping.
Set<String> values = new Set<String>();
Set<Object> generic = new Set<Object>((List<Object>)new List<String>(values));
It's not immediately clear if this song and dance is even faster than looping anyway.
So you can try like this
map<string,string> newMap= new Map<string,string>();
for(String strKey: mapValues.keyset())
{
newMap.put(strKey, String.valueof(mapValues.get(strKey)));
}
I have tried this worked for me:
enter code here
map<string,object> mspstrToObj = new Map<string,object>();
mspstrToObj.put('key1', 'obj1');
map<string,string> mspstrTostr = new Map<string,string>();
mspstrTostr.put('strKey1',string.valueof(mspstrToObj.get('key1')));
system.debug('=======mspstrTostr====='+mspstrTostr);
You need to create new Map and put the values as per above.
RestContext.response.responseBody = Blob.valueOf(JSON.serialize(locations));
JSON can handle almost any data type, including maps that include serializable types. The exceptions to this rule are items that can't be serialized, like SavePoint, SObjectField and so on.
If you really want to convert a Map to String you can do it by using String.valueOf()
Map<String, Integer> mapVal = new Map<String, Integer> {'zero' => 0, 'one' => 1, 'two' => 2, 'three' => 3};
String mapString = String.valueOf(mapVal);
I suspect what you want to do is really convert to JSON, which in that case you would do JSON.serialize as sfdcfox suggested.